我有一个整数列表列表,如:
A -> 10 10 1 1 1
B -> 10 9 9 7 6
...
我想根据他们有多少10个,然后是多少9s,8s,7s等等来对它们进行排序
因此,在上面的示例中,A应该优于B,因为即使总点数较少,它也有两个10而不是一个。
代码应该是通用的,因为我不知道每种情况可以使用多少个数字(有时10个,有时5个,甚至只有3个)。
我开发了类似的东西:lists.OrderByDescending(a => a.Where(b => b == 10).Count()).
ThenByDescending(a => a.Where(b => b == 9).Count()).
依此类推,但这不是通用的......
我希望问题很清楚......非常感谢你!
答案 0 :(得分:2)
您可以创建按数量为10的订单列表查询,然后通过为9到1的数字添加其他订单来撰写查询:
var query = lists.OrderByDescending(l => l.Count(x => x == 10));
for (int i = 9; i >= 1; i--)
query = query.ThenByDescending(l => l.Count(x => x == i));
对于这些样本列表:
var lists = new[] {
new[] { 10, 9, 9, 8, 7 },
new[] { 10, 9, 9, 7, 6 },
new[] { 10, 10, 1, 1, 1 }
};
结果将是:
[10, 10, 1, 1, 1]
[10, 9, 9, 8, 7]
[10, 9, 9, 7, 6]
这很简单,但效率不高。如果您需要更好的性能,请考虑创建自定义比较器。以下是带有比较器的示例,它使用压缩有序序列来检查序列中的所有项目是否相同,或者获取不同的第一项:
public class CustomComparer : Comparer<IList<int>>
{
public override int Compare(IList<int> x, IList<int> y)
{
var comparisons = x.Zip(y, (a,b) => a.CompareTo(b));
foreach(var comparison in comparisons)
{
if (comparison != 0)
return comparison;
}
return x.Count.CompareTo(y.Count);
}
}
注意:如果没有订购列表中的项目,那么您应该在压缩之前对它们进行排序:
var comparisons =
x.OrderByDescending(i => i)
.Zip(y.OrderByDescending(i => i), (a,b) => a.CompareTo(b));
它非常简单。考虑两个列表:
[10, 9, 9, 8, 7, 5]
[10, 9, 9, 7, 6]
它将在相应的位置创建成对的项目:
{10,10}, {9,9}, {9,9}, {8,7}, {7,6}
然后逐一比较每对中的项目,直到找到第一个不匹配:
0, 0, 0, 1 (four comparisons only)
这意味着第一个列表比第二个列表多8个。用法:
var query = lists.OrderByDescending(i => i, new CustomComparer());
结果相同。
答案 1 :(得分:1)
比较列表并返回常规比较结果 - 返回1,0或-1,具体取决于一个值是否大于,等于或小于另一个值。
static int CompareLists(List<int> a, List<int> b)
{
var grpA = a.GroupBy(p => p).ToDictionary(k=>k.Key,v=>v.Count());
var grpB = b.GroupBy(p => p).ToDictionary(k=>k.Key,v=>v.Count());
for (int i = 10; i >= 0; i--)
{
int countA = grpA.ContainsKey(i) ? grpA[i] : 0;
int countB = grpB.ContainsKey(i) ? grpB[i] : 0;
int comparison = countA.CompareTo(countB);
if (comparison != 0)
return comparison;
}
return 0;
}
首先,我们将列表转换为number->amount of occurences
的字典。
然后我们迭代从10到0的数字并比较出现的次数。如果结果为0,那么我们转到另一个数字。
如果您要List<List<int>>
进行排序,只需使用list.Sort(CompareLists)
,如下所示:
List<int> d = new List<int> { 10, 6, 6 };
List<int> b = new List<int> { 10, 9, 9 };
List<int> a = new List<int> { 10, 10, 1, 1, 1 };
List<int> c = new List<int> { 10, 7, 7 };
List<int> e = new List<int> { 9, 3, 7 };
List<int> f = new List<int> { 9, 9, 7 };
List<List<int>> list = new List<List<int>>() { a, b, c, d, e, f };
list.Sort(CompareLists);
答案 2 :(得分:1)
以下比较器
public class Comparer : IComparer<IEnumerable<int>>
{
public int Compare(IEnumerable<int> a, IEnumerable<int> b)
{
var aOrdered = a.OrderByDescending(i => i).Concat(new[] { int.MinValue });
var bOrdered = b.OrderByDescending(i => i).Concat(new[] { int.MinValue });
return a.Zip(b, (i, j) => i.CompareTo(j)).FirstOrDefault(c => c != 0);
}
}
允许您订购列表列表
var result = lists.OrderByDescending(i => i, new Comparer());
没有遍历每个列表十次计算单个元素。