在C#中创建一个不同的列表

时间:2013-08-13 18:14:07

标签: c# linq list distinct

在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”方法,但它仍然无法解决我的问题,即根据其中一个键值对呈现列表。

5 个答案:

答案 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)

您可以将值分组,然后将所有键或其他有用的内容相加