我有一组对象本身包含一组。
private class Pilot
{
public string Name;
public HashSet<string> Skills;
}
以下是一些测试数据:
public void TestSetComparison()
{
var pilots = new[]
{
new Pilot { Name = "Smith", Skills = new HashSet<string>(new[] { "B-52", "F-14" }) },
new Pilot { Name = "Higgins", Skills = new HashSet<string>(new[] { "Concorde", "F-14" }) },
new Pilot { Name = "Jones", Skills = new HashSet<string>(new[] { "F-14", "B-52" }) },
new Pilot { Name = "Wilson", Skills = new HashSet<string>(new[] { "F-14", "Concorde" }) },
new Pilot { Name = "Celko", Skills = new HashSet<string>(new[] { "Piper Cub" }) },
};
我想在Linq中使用OrderBy
,以便:
我认为我需要实现IComparer<Pilot>
传递给OrderBy
,但不知道如何处理“无关紧要”方面(上图)和稳定排序。
更新
我希望输出为相同的五个 Pilot
个对象的数组,但是不同的顺序。
答案 0 :(得分:7)
当GroupBy
你必须为你要分组的类型IEqualityComparer<T>
实施HashSet<string>
时,例如。
private sealed class MyComparer : IEqualityComparer<HashSet<string>> {
public bool Equals(HashSet<string> x, HashSet<string> y) {
if (object.ReferenceEquals(x, y))
return true;
else if (null == x || null == y)
return false;
return x.SetEquals(y);
}
public int GetHashCode(HashSet<string> obj) {
return obj == null ? -1 : obj.Count;
}
}
然后使用它:
IEnumerable<Pilot> result = pilots
.GroupBy(pilot => pilot.Skills, new MyComparer())
.Select(chunk => string.Join(", ", chunk
.Select(item => item.Name)
.OrderBy(name => name))); // drop OrderBy if you want stable Smith, Jones
Console.WriteLine(string.Join(Environment.NewLine, result));
结果:
Jones, Smith
Higgins, Wilson
Celko
修改:如果您想要重新设置数组,请添加SelectMany()
以便展平分组和最终{{ 1}}:
ToArray()
结果:
var result = pilots
.GroupBy(pilot => pilot.Skills, new MyComparer())
.SelectMany(chunk => chunk)
.ToArray();
Console.WriteLine(string.Join(", ", result.Select(p => p.Name)));
请注意,string.join将每个组的名称组合在一行中,即 Jones, Smith,
Higgins, Wilson,
Celko
都具有相同的技能组合。
将其作为 DotNetFiddle
运行答案 1 :(得分:1)
您可以使用 HashSetByItemsComparer 的以下实现来完成您的需要:
public class HashSetByItemsComparer<TItem> : IComparer<HashSet<TItem>>
{
private readonly IComparer<TItem> _itemComparer;
public HashSetByItemsComparer(IComparer<TItem> itemComparer)
{
_itemComparer = itemComparer;
}
public int Compare(HashSet<TItem> x, HashSet<TItem> y)
{
foreach (var orderedItemPair in Enumerable.Zip(
x.OrderBy(item => item, _itemComparer),
y.OrderBy(item => item, _itemComparer),
(a, b) => (a, b))) //C# 7 syntax used - Tuples
{
var itemCompareResult = _itemComparer.Compare(orderedItemPair.a, orderedItemPair.b);
if (itemCompareResult != 0)
{
return itemCompareResult;
}
}
return 0;
}
}
它可能不是最有效的解决方案,因为它分别为每个比较命令哈希集。如果使用数百万飞行员和许多技能,您可能需要对其进行优化,但对于小数字,它可以正常工作。
用法示例:
var sortedPilots = pilots.OrderBy(p => p.Skills, new HashSetByItemsComparer<string>(StringComparer.Ordinal));
foreach (var pilot in sortedPilots)
{
Console.WriteLine(pilot.Name);
}
输出是:
Smith
Jones
Higgins
Wilson
Celko
所以它会保留相同的项目排序(OrderBy
的默认行为 - 您无需担心)。顺便说一下,GroupBy
的解决方案不允许你根据我的知识恢复项目顺序。
答案 2 :(得分:0)
以下是orderby
的示例 var groups = from c in GridImage (Your List)
orderby c.grouping (Your Item inside List)
group c by c.grouping;