我从XML中设置了以下项目:
id category 5 1 5 3 5 4 5 3 5 3
我需要这些项目的清单:
5 1 5 3 5 4
如何在LINQ中区分Category AND Id?
您是否想要通过多个字段区分?如果是这样,只需使用匿名类型和Distinct运算符,它应该没问题:
var query = doc.Elements("whatever") .Select(element => new { id = (int) element.Attribute("id"), category = (int) element.Attribute("cat") }) .Distinct();
如果您正在尝试获取"更大"类型的一组不同的值,但只查看不同方面的某些属性子集,则可能需要DistinctBy
在MoreLINQ中实现DistinctBy.cs
:
public static IEnumerableDistinctBy ( this IEnumerable source, Func keySelector, IEqualityComparer comparer) { HashSet knownKeys = new HashSet (comparer); foreach (TSource element in source) { if (knownKeys.Add(keySelector(element))) { yield return element; } } }
(如果您null
作为比较器传入,它将使用键类型的默认比较器.)
只需使用Distinct()
您自己的比较器.
http://msdn.microsoft.com/en-us/library/bb338049.aspx
除了Jon Skeet的答案之外,您还可以使用group by表达式来获取每个组迭代的唯一组和计数:
var query = from e in doc.Elements("whatever") group e by new { id = e.Key, val = e.Value } into g select new { id = g.Key.id, val = g.Key.val, count = g.Count() };
对于任何仍在寻找的人; 这是实现自定义lambda比较器的另一种方法.
public class LambdaComparer: IEqualityComparer { private readonly Func _expression; public LambdaComparer(Func lambda) { _expression = lambda; } public bool Equals(T x, T y) { return _expression(x, y); } public int GetHashCode(T obj) { /* If you just return 0 for the hash the Equals comparer will kick in. The underlying evaluation checks the hash and then short circuits the evaluation if it is false. Otherwise, it checks the Equals. If you force the hash to be true (by assuming 0 for both objects), you will always fall through to the Equals check which is what we are always going for. */ return 0; } }
然后,您可以为linq Distinct创建一个可以接受lambda的扩展
public static IEnumerableDistinct (this IEnumerable list, Func lambda) { return list.Distinct(new LambdaComparer (lambda)); }
用法:
var availableItems = list.Distinct((p, p1) => p.Id== p1.Id);
我的答案有点迟了,但是如果你想要整个元素,你可能想要这样做,而不仅仅是想要分组的值:
var query = doc.Elements("whatever") .GroupBy(element => new { id = (int) element.Attribute("id"), category = (int) element.Attribute("cat") }) .Select(e => e.First());
这将通过选择为您提供与您的组匹配的第一个完整元素,就像Jon Skeets使用DistinctBy的第二个示例,但没有实现IEqualityComparer比较器.DistinctBy很可能会更快,但如果性能不是问题,上面的解决方案将涉及更少的代码.