5

在 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 对象类型列表,我想操作该列表,以便我只获得唯一值并且我只基于国家名称。因此,我希望列表减少到只有一个“国家”、“美国”,即使它出现不止一次。

我正在研究 linq Distinct,但它没有做我想要的,因为它我无法定义任何参数,而且它似乎无法捕获两个 A 类型的等效对象。我知道我可以覆盖"Equals" 方法,但它仍然不能解决我的问题,即根据一个键值对来呈现不同的列表。

4

5 回答 5

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 版本中,您可以使用 aHashSet<T>而不是 a Dictionary<T, Bool>,因为我们并不真正关心该值是什么,因为它已经被散列了。

于 2013-08-13T18:51:08.770 回答
1

您需要先选择 distinct 属性:

因为它是列表中的列表,所以可以使用 SelectMany。SelectMany 将连接子选择的结果。

List<A> listOfA = new List<A>();

listOfA.SelectMany(a => a.KeyValuePairs
    .Where(keyValue => keyValue.Key == "Country")
        .Select(keyValue => keyValue.Value))
            .Distinct();

这应该是它。它将选择键为“国家/地区”的所有值并连接列表。最终它将与国家不同。假设 A 类的属性 KeyValuePairs 至少是一个 IEnumerable< KeyValuePair< string, string>>

于 2013-08-13T18:17:08.143 回答
1

查看morelinq 项目DistinctBy中的语法。

A a = new A(keyValuePairs);

a = a.DistinctBy(k => new { k.Key, k.Value }).ToList();
于 2013-08-13T18:17:46.970 回答
1
var result = keyValuePairs.GroupBy(x => x.Key)
                          .SelectMany(g => g.Key == "Country" ?  g.Distinct() : g);
于 2013-08-13T18:22:31.677 回答
0

您可以使用 groupby 语句。从这里你可以做各种很酷的东西

listOfA.GroupBy(i=>i.Value)

您可以按值分组,然后对所有键或其他有用的东西求和

于 2013-08-13T18:18:42.907 回答