Проблема с дубликатами C#
Всем привет, я новичок и столкнулся с проблемой моего решения. Дана строка по типу "130 12 111 508 54 78 1110". Каждое число в строке имеет свой "вес", который состоит из сумы цифр. Например 130 имеет "вес" 4, т.к. 1+3+0 = 4. Все числа в строке - положительные. Задача вернуть строку, отсортированную "по весу", но при этом сохраняя первоначальный вид числа.
К примеру строка "130 12 111 508 54 78 1110" станет "111 1110 12 130 54 508 78"
У меня вышел такой код
static void Main(string[] args)
{
Console.WriteLine(Order("130 12 111 508 54 78 1110"));
}
public static string Order(string input)
{
string[] Subs = input.Split(' ', StringSplitOptions.RemoveEmptyEntries).ToArray();
Dictionary<string, int> Orders = new Dictionary<string, int>();
foreach(string sub in Subs)
{
Orders.Add(sub, ReturnSumOfString(sub));
}
Orders = Orders.OrderBy(pair => pair.Value).ThenBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
StringBuilder newstr = new StringBuilder("");
foreach (var num in Orders)
{
newstr.Append(num.Key + " ");
}
return newstr.ToString();
}
public static int ReturnSumOfString(string input)
{
int[] vs = input.ToCharArray().Select(x => int.Parse(x.ToString())).ToArray();
return vs.Sum();
}
И он вроде работает правильно, но я столкнулся с проблемой, что он не будет работать, если в строке повторяются числа. Проблема как я понял, в словаре, что он не может иметь двух одинаковых ключей, на которых завязано моё решение с сопоставлением чисел. Как можно решить проблему с повторениями?
Ответы (2 шт):
Я бы на вашем месте тогда хранил бы словарь, где ключ - это сумма цифр, а значение = это список чисел с такой сумоой.
Код
void Main()
{
Console.WriteLine(Order("130 12 111 508 54 78 1110 1110"));
}
public static string Order(string input)
{
string[] subs = input.Split().ToArray();
var orders = new Dictionary<int, List<string>>();
foreach (string sub in subs)
{
var sum = ReturnSumOfString(sub);
if (!orders.ContainsKey(sum)) orders[sum] = new List<string>();
orders[sum].Add(sub);
}
var ordered = orders.OrderBy(x=>x.Key).SelectMany(x=>x.Value);
StringBuilder newstr = new StringBuilder("");
foreach (var num in ordered)
{
newstr.Append(num + " ");
}
return newstr.ToString();
}
public static int ReturnSumOfString(string input)
{
int[] vs = input.ToCharArray().Select(x => int.Parse(x.ToString())).ToArray();
return vs.Sum();
}
Вывод
12 111 1110 1110 130 54 508 78
Есть ещё более короткий вариант, но он опирается на факт, что linq сортировка сама по себе стабильная.
void Main()
{
Console.WriteLine(Order("130 12 111 508 54 78 1110 1110"));
}
public static string Order(string input)
{
string[] subs = input.Split();
var ordered = subs.OrderBy(x=>ReturnSumOfString(x));
StringBuilder newstr = new StringBuilder("");
foreach (var num in ordered)
newstr.Append(num + " ");
return newstr.ToString();
}
public static int ReturnSumOfString(string input)
{
int[] vs = input.ToCharArray().Select(x => int.Parse(x.ToString())).ToArray();
return vs.Sum();
}
Вывод
12 111 1110 1110 130 54 508 78
Можно также закешировать суммы чисел, чтобы много раз не пересчитывать, результат будет тот же
var ordered = subs.Select(x=>(v:x, sum:ReturnSumOfString(x))).OrderBy(x=>x.sum);