【问题标题】:LINQ distinct with corresponding counts based on a List propertyLINQ 与基于 List 属性的相应计数不同
【发布时间】:2015-05-01 03:51:48
【问题描述】:

我有以下课程

public class Photo
{
    public int Id { get; set; }
    public string Caption { get; set; }
    public Collection<string> Tags { get; set; }
}

一张照片可以有多个与之关联的标签,同一个标签可以用在任意数量的不同照片中。

我最终想要做的是检索不同标签的列表,计算每个标签分配了多少张照片。

我无法控制基础数据 - 我正在使用一个 API,该 API 具有我用来检索照片集合的 Search 方法,但没有获取不同标签列表的方法。

所以我的问题是,如果我有大量照片,我如何使用 LINQ 获取此列表中包含的标签的不同列表,并获取每个标签的(照片)计数?

【问题讨论】:

  • 不确定您要什么...您尝试过什么?
  • 嗯,试试List&lt;Photos&gt;.Where(y = List&lt;Photos&gt;.Select(x = x.Tag).Distinct().Contains(y.Tag))).Count()

标签: c# .net linq


【解决方案1】:
var tagCounts = photos
    .SelectMany(photo => photo.Tags)
    .GroupBy(tag => tag, (tag, group) => new { tag, count = group.Count() })
    .ToDictionary(tuple => tuple.tag, tuple => tuple.count);

推理如下。

  • 获取所有标签的顺序,如果多张照片具有相同的标签,则重复。
  • 重复标签按值分组,统计每组标签个数。
  • 构建从每个标签到具有该标签的照片数量的字典映射。

【讨论】:

    【解决方案2】:

    你可以像这样使用SelectMany & GroupBy:-

    var result = photos.SelectMany(x => x.Tags, (photosObj, tags) => new {photosObj, tags})
                       .GroupBy(x => x.tags)
                       .Select(x => new
                             {
                                Tags = x.Key,
                                PhotoId = String.Join(",",x.Select(z => z.photosObj.Id))
                             });
    

    这将以逗号分隔的格式为您提供所有标签及其各自的PhotoIds

    更新:

    抱歉,刚刚注意到您需要 Photos 对象的计数,在这种情况下您只需要这个:-

    var result = photos.SelectMany(x => x.Tags)
                       .GroupBy(x => x)
                       .Select(x => new
                                  {
                                      Tags = x.Key,
                                      PhotoCount = x.Count()
                                  });
    

    所以,假设你有这个数据:-

     List<Photo> photos = new List<Photo>
     {
         new Photo { Id =1, Caption = "C1", Tags = new List<string> { "T1", "T2", "T3" }},
         new Photo { Id =2, Caption = "C2", Tags = new List<string> { "T4", "T2", "T5" }},
         new Photo { Id =3, Caption = "C3", Tags = new List<string> { "T5", "T3", "T2" }}
     };
    

    你会在下面输出:-

    【讨论】:

      【解决方案3】:

      您可以分两步完成。

      • 首先从列表中获取不同的标签
      • 遍历不同的标签并从列表中获取计数并将其放入Dictionary&lt;string,int&gt;

      类似:

      List<Photo> list = new List<Photo>();
      var distinctTags = list.SelectMany(r => r.Tags).Distinct();
      Dictionary<string, int> dictionary = new Dictionary<string, int>();
      foreach (string tag in distinctTags)
      {
          dictionary.Add(tag, list.Count(r=> r.Tags.Contains(tag)));
      }
      

      【讨论】:

      • 不显示如何获得计数,就像问的问题一样
      • 每个标签的计数?应该这样做dictionary.Add(tag, list.Count(r=&gt; r.Tags.Contains(tag)));
      【解决方案4】:
      var list=new[]{
         new {id=1,Tags=new List<string>{"a","b","c"}},
         new {id=2,Tags=new List<string>{"b","c","d"}},
         new {id=3,Tags=new List<string>{"c","d","e"}},
      };
      var result=list.SelectMany(r=>r.Tags)
         .GroupBy(r=>r,r=>r,(Key,Vals)=>new {Tag=Key,Count=Vals.Count()});
      

      结果:

      Tag Count
      a 1 
      b 2 
      c 3 
      d 2 
      e 1 
      

      【讨论】:

        猜你喜欢
        • 2018-11-19
        • 2017-03-15
        • 1970-01-01
        • 2022-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多