所以,说我有以下内容:
public class Element
{
public int ID;
public int Type;
public Properties prorerty;
...
}
和
public class Properties
{
public int Id;
public string Property;
...
}
我有一份清单:
List Elements = new List();
在Element类的prorerty列中获取所有不同值的列表最简洁的方法是什么?我的意思是,我可以遍历列表并将所有不重复的值添加到另一个字符串列表中,但这看起来很脏且效率低下。我有一种感觉,有一些神奇的Linq结构可以在一行中完成,但我无法想出任何东西。
答案 0 :(得分:7)
var results = Elements.Distinct();
注意:您必须覆盖.Equals
和.GetHashCode()
public class Element : IEqualityComparer<Element>
{
public bool Equals(Element x, Element y)
{
if (x.ID == y.ID)
{
return true;
}
else
{
return false;
}
}
}
public int GetHashCode(Element obj)
{
return obj.ID.GetHashCode();
}
答案 1 :(得分:0)
var props = Elements.Select(x => x.Properties).Distinct();
并确保您覆盖了.Equals()
和.GetHashCode()
方法
或者如果您需要来自Properties
的直接字符串:
var props = Elements
.Select(x => x.Properties != null ? x.Properties.Property : null)
.Distinct();
答案 2 :(得分:0)
如果您需要Properties
字段上的字符串字段,并且如果您知道Properties
字段prorerty
永远不会null
,请使用
IEnumerable<string> uniqueStrings = Elements
.Select(e => e.prorerty.Property).Distinct();
如果prorerty
有机会为null,请在lambda中处理这种情况。
这将使用String
的默认相等比较器,这是一个独立于文化和区分大小写的序数比较。
答案 3 :(得分:0)
我在LINQPad(C#程序)中的工作示例
void Main()
{
var ret = new List<Element>();
ret.Add(new Element(){ID=1});
ret.Add(new Element(){ID=1});
ret.Add(new Element(){ID=2});
ret = ret.GroupBy(x=>x.ID).Select(x=>x.First()).ToList();
Console.WriteLine(ret.Count()); // shows 2
}
public class Element
{
public int ID;
public int Type;
public Properties prorerty;
}
public class Properties
{
public int Id;
public string Property;
}
答案 4 :(得分:0)
使用下面显示的方法之一是不是更简单:)?您可以通过某个键对域对象进行分组,然后选择FirstOrDefault,如下所示。 这是我在类似问题上的答案的副本: Get unique values - original answer
更有趣的选择是创建一些Comparer适配器,它接收域对象并创建Comparer可以使用/开箱即用的其他对象。基于比较器,您可以创建自定义linq扩展,如下面的示例所示。希望它有所帮助:)
t.erase(std::next(t.begin(), i));
自定义比较器适配器:
[TestMethod]
public void CustomDistinctTest()
{
// Generate some sample of domain objects
var listOfDomainObjects = Enumerable
.Range(10, 10)
.SelectMany(x =>
Enumerable
.Range(15, 10)
.Select(y => new SomeClass { SomeText = x.ToString(), SomeInt = x + y }))
.ToList();
var uniqueStringsByUsingGroupBy = listOfDomainObjects
.GroupBy(x => x.SomeText)
.Select(x => x.FirstOrDefault())
.ToList();
var uniqueStringsByCustomExtension = listOfDomainObjects.DistinctBy(x => x.SomeText).ToList();
var uniqueIntsByCustomExtension = listOfDomainObjects.DistinctBy(x => x.SomeInt).ToList();
var uniqueStrings = listOfDomainObjects
.Distinct(new EqualityComparerAdapter<SomeClass, string>(x => x.SomeText))
.OrderBy(x=>x.SomeText)
.ToList();
var uniqueInts = listOfDomainObjects
.Distinct(new EqualityComparerAdapter<SomeClass, int>(x => x.SomeInt))
.OrderBy(x => x.SomeInt)
.ToList();
}
自定义linq扩展(DistinctBy扩展方法的定义):
public class EqualityComparerAdapter<T, V> : EqualityComparer<T>
where V : IEquatable<V>
{
private Func<T, V> _valueAdapter;
public EqualityComparerAdapter(Func<T, V> valueAdapter)
{
_valueAdapter = valueAdapter;
}
public override bool Equals(T x, T y)
{
return _valueAdapter(x).Equals(_valueAdapter(y));
}
public override int GetHashCode(T obj)
{
return _valueAdapter(obj).GetHashCode();
}
}
测试用例中使用的域类的定义:
// Embed this class in some specific custom namespace
public static class DistByExt
{
public static IEnumerable<T> DistinctBy<T,V>(this IEnumerable<T> enumerator,Func<T,V> valueAdapter)
where V : IEquatable<V>
{
return enumerator.Distinct(new EqualityComparerAdapter<T, V>(valueAdapter));
}
}