在C#中,我有一个对象类型'A',它包含一个键值对列表。
键值对是类别字符串和值字符串。
要实例化对象类型A,我必须执行以下操作:
List<KeyValuePair> keyValuePairs = new List<KeyValuePair>();
keyValuePairs.Add(new KeyValuePair<"Country", "U.S.A">());
keyValuePairs.Add(new KeyValuePair<"Name", "Mo">());
keyValuePairs.Add(new KeyValuePair<"Age", "33">());
A a = new A(keyValuePairs);
最终,我将有一个A对象类型的列表,我想操纵列表,以便我只获得唯一值,我只根据国家名称。因此,我希望将列表缩减为只有一个“国家”,“美国A”,即使它出现不止一次。
我正在调查linq Distinct,但它没有做我想要的,因为我无法定义任何参数,因为它似乎无法捕获两个类型A的等效对象。我知道我可以覆盖“Equals”方法,但它仍然无法解决我的问题,即根据其中一个键值对呈现列表。
答案 0 :(得分:2)
为了扩展Karl Anderson关于使用morelinq的建议,如果你无法(或者不想)链接到你的项目的另一个dll,我自己实现了这个:
public static IEnumerable<T> DistinctBy<T, U>(this IEnumerable<T> source, Func<T, U>selector)
{
var contained = new Dictionary<U, bool>();
foreach (var elem in source)
{
U selected = selector(elem);
bool has;
if (!contained.TryGetValue(selected, out has))
{
contained[selected] = true;
yield return elem;
}
}
}
使用如下:
collection.DistinctBy(elem => elem.Property);
在支持它的.NET版本中,您可以使用HashSet<T>
而不是Dictionary<T, Bool>
,因为我们并不关心它的值是多少,因为它已经被散列
答案 1 :(得分:1)
您需要先选择不同的属性:
因为它是列表中的列表,所以您可以使用SelectMany。 SelectMany将连接子选择的结果。
List<A> listOfA = new List<A>();
listOfA.SelectMany(a => a.KeyValuePairs
.Where(keyValue => keyValue.Key == "Country")
.Select(keyValue => keyValue.Value))
.Distinct();
这应该是它。它将选择键为“Country”的所有值并连接列表。最终它将区分国家。假定类A的属性KeyValuePairs至少是IEnumerable&lt; KeyValuePair&LT;字符串,字符串&gt;&gt;
答案 2 :(得分:1)
查看morelinq project中的DistinctBy
语法。
A a = new A(keyValuePairs);
a = a.DistinctBy(k => new { k.Key, k.Value }).ToList();
答案 3 :(得分:1)
var result = keyValuePairs.GroupBy(x => x.Key)
.SelectMany(g => g.Key == "Country" ? g.Distinct() : g);
答案 4 :(得分:0)
您可以使用groupby语句。从这里你可以做各种酷的stuf
listOfA.GroupBy(i=>i.Value)
您可以将值分组,然后将所有键或其他有用的内容相加