查找相等的字符串集及其计数(不同的列表)

时间:2015-05-19 02:57:10

标签: c# linq count set distinct

我正试图找到不同的集合及其数量。

假设你有以下型号。

public class AModel {
   public IList<string> Tags { get; set; }
}

你有一个上面模型的列表,假设有{000}个AModel个实例,其中包含1 ... N Tags

我需要找到使用高性能LINQ的不同Tags,列出不是列表值(顺序无关紧要,计数和标记字符串问题)。

示例:

List<AModel> models = new List<AModel>{
   new AModel { Tags = new List<string> { "Tag1", "Tag2" } },
   new AModel { Tags = new List<string> { "Tag2", "Tag1" } },
   new AModel { Tags = new List<string> { "Tag1", "Tag1" } },
   new AModel { Tags = new List<string> { "Tag2", "Tag2" } },
   new AModel { Tags = new List<string> { "Tag2", "Tag2" } },
};

所以,我需要一个结果:

List: { "Tag1", "Tag2" } Count: 2
List: { "Tag1", "Tag1" } Count: 1
List: { "Tag2", "Tag2" } Count: 2

到目前为止,我已经检查了SetEquals和SequenceEquals。我可以迭代到所有模型的所有标签,并保持计数和相等的集合,如果我已经检查它,则通过下一个,但它具有反效率。

2 个答案:

答案 0 :(得分:1)

我接近这个问题的方法是首先对标签进行排序然后将它们组合起来制作一个唯一的密钥,然后我可以使用line to group by。分组应该自动向我提供密钥和计数。

这是一个让你开始的草稿:

foreach(var value in models.Select(model => String.Join(";", model.Tags.OrderBy(tags => tags))).GroupBy(list => list))
{
     Console.WriteLine(value.Key + "," + value.Count());
}

输出与您想要的非常相似:

Tag1中; Tag2,2
TAG1; Tag1,1
TAG2; Tag2,2

答案 1 :(得分:1)

实施EqualityComparer<IList<string>>

public override bool Equals(IList<string> x, IList<string> y)
{
    return Enumerable.SequenceEqual(x.OrderBy(i => i), y.OrderBy(i => i));
}

public override int GetHashCode(IList<string> obj)
{
    return obj.Select(i => i.GetHashCode()).Average().GetHashCode();
}

在linq groupby中使用

List<AModel> models = new List<AModel>() {
    new AModel { Tags = new List<string> { "Tag1", "Tag2" } },
    new AModel { Tags = new List<string> { "Tag2", "Tag1" } },
    new AModel { Tags = new List<string> { "Tag1", "Tag1" } },
    new AModel { Tags = new List<string> { "Tag2", "Tag2" } },
    new AModel { Tags = new List<string> { "Tag2", "Tag2" } },
};

var result = models
    .GroupBy(i => i.Tags, new ListEqualityComparer())
    .Select(i => new { Tags = i.Key, Count = i.Count() });