示例:
a =" 56 65 74 100 99 68 86 180 90",按数字排序变为:" 100 180 90 56 65 74 68 86 99"
当两个数字具有相同的"权重"时,让我们将它们分类为字符串而不是数字:100在180之前,因为它的重量是#34; (1)小于180(9)之一,180之前是90,因为,具有相同的"权重" (9)它以字符串形式出现。
列表中的所有数字都是正数,列表可以为空。
我的测试:
[TestMethod]
public void Test1()
{
Assert.AreEqual("2000 103 123 4444 99", WeightSort.orderWeight("103 123 4444 99 2000"));
}
[TestMethod]
public void Test2()
{
Assert.AreEqual("11 11 2000 10003 22 123 1234000 44444444 9999", WeightSort.orderWeight("2000 10003 1234000 44444444 9999 11 11 22 123"));
}
我的班级来计算权重的顺序:
public class WeightSort
{
public static string orderWeight(string strng)
{
List<int> list = strng.Split(' ').Select(Int32.Parse).OrderBy(i => i).ToList();
List<int> SumofNums = new List<int>();
List<string> SumandNums = new List<string>();
List<string> SumandNums2 = new List<string>();
List<string> Nums = new List<string>();
foreach (var itm in list)
{
int num = (int)GetSumOfDigits(itm);
SumofNums.Add(num);
SumandNums.Add(itm + "," + num);
}
SumofNums = SumofNums.OrderBy(i => i).ToList();
string txt = "";
foreach (var itm in SumofNums)
{
var item = itm.ToString();
if (!Nums.Contains(item))
{
foreach (var itm2 in SumandNums)
{
var itm3 = itm2.Split(',');
if (item == itm3[1])
{
SumandNums2.Add(itm2);
if (string.IsNullOrEmpty(txt))
txt = itm3[0];
else
txt = txt + " " + itm3[0];
}
}
Nums.Add(item);
}
}
return txt;
}
static long GetSumOfDigits(long n)
{
long num2 = 0;
long num3 = n;
long r = 0;
while (num3 != 0)
{
r = num3 % 10;
num3 = num3 / 10;
num2 = num2 + r;
}
return num2;
}
}
如果只有一个但不重复,我可以处理。 请帮我改写我的课程,这样它也可以处理重复的内容。
数字之和:
string weights = "103 123 4444 99 2000";
1) 2000, digit sum = 2;
2) 103, digit sum = 4;
3) 123, digit sum = 6;
4) 4444, digit sum = 16;
5) 99, digit sum = 18;
the correct order is "2000 103 123 4444 99"
答案 0 :(得分:5)
如果按重量排序,则可以使用 Linq
实施
String a = "56 65 74 100 99 68 86 180 90";
// 100 180 90 56 65 74 68 86 99
String result = String.Join(" ", a
.Split(' ')
.OrderBy(item => item.Sum(ch => ch - '0')) // sum of digits
.ThenBy(item => item)); // lexicographic ("as string")
答案 1 :(得分:2)
试试这个:
var input = "103 123 4444 99 2000";
var sorted = input.Split(' ').OrderBy(s => s.Sum(c => c - '0')).ThenBy(s => s);
var result = string.Join(" ", sorted);
另外:我现在意识到,在我发布我的答案之前,Dmitry的答案已经演变成与我的相同。
新增内容:如果您发现s.Sum(c => c - '0')
就像黑客一样,您可以using System.Globalization;
代替s.Sum((Func<char, int>)CharUnicodeInfo.GetDecimalDigitValue)
。
您可以在lambda中进行验证。例如:
var sorted = input.Split(' ')
.OrderBy(s => s.Sum(c => { if (c < '0' || c > '9') { throw new ArgumentOutOfRangeException("c", "Unexpected character."); } return c - '0'; }))
.ThenBy(s => s);
答案 2 :(得分:0)
您也可以通过创建一个比较器来完成此操作,该比较器会告诉您某个值是否大于或小于另一个值然后可以使用。代码在很大程度上说明了一切:
void Main()
{
var strings = new List<string>("2000 10003 1234000 44444444 9999 11 11 22 123".Split(' '));
strings.Sort(new MyComparer());
Console.WriteLine(String.Join(" ", strings));
}
public class MyComparer : IComparer<string>
{
public int Compare(string a, string b)
{
var aWeight = GetWeight(a);
var bWeight = GetWeight(b);
if (aWeight==bWeight)
{
return String.Compare(a,b);
}
else
{
return aWeight < bWeight ? -1 : 1;
}
}
private int GetWeight(string number)
{
var weight = 0;
foreach(var digit in number)
{
weight+=Int32.Parse(digit.ToString());
}
return weight;
}
}
关键是MyComparer
类定义了一个带有两个值的公共方法。它获取对象的权重,如果它们相同则返回字符串比较。
然后可以将此比较器传递给List<T>
之类的排序函数,然后进行排序。
这个更长,但我认为它值得分享,因为它更可重用(例如,如果你在代码中的很多地方都这样做,你可以将你的逻辑放在一个单独的类中),它有时可能是一个更具可读性。
我还注意到我不是ch - '0'
的粉丝,因为它不是一目了然的,如果你不知道这个诀窍的话。同样在非数字字符的情况下,它仍然会做一些事情,但不一定是明智的。如果您传递任何非数字数据,我将抛出一个很好的老式异常。
答案 3 :(得分:-1)
我发现这个解决方案非常简短明了:
var orderedNumbers = "56 65 74 100 99 68 86 180 90".Split(' ')
.OrderBy(GetWeight)
.ThenBy(x => x);
var result = String.Join(" ", orderedNumbers);
这将首先计算任何给定数字的权重并按此值排序。如果它相等,则ThenBy
- 子句进入游戏并通过执行字符串比较进一步对结果进行排序(因为第一个OrderBy
返回的值是字符串列表)。
用
int GetWeight(string number)
{
return number.Sum(x => CharUnicodeInfo.GetDecimalDigitValue(x));
}