【问题标题】:C# Linq to Group to a list if a Condition meets else do not group如果条件满足,C# Linq to Group to a list else do not group
【发布时间】:2017-09-02 19:54:23
【问题描述】:

我有一个清单
我的要求

如果条件满足,我需要一个 LINQ lambda 查询来分组到列表,否则不分组。

即在一个条件下我希望它被分组
否则不应分组

我已经搜索过网络 - 我得到了有关条件分组的详细信息,但我无法理解如何在没有分组的情况下包含剩余项目。

在网上找到的一些信息用于有条件地分组 - 但是那些不符合条件的项目不会包含在结果列表中。

举例

列表 = [{1,"a"},{40,""),{9,"a"},{52,"b"),{2,"b"},{99,""),{88, "b"}]

预期的结果列表将按 a,b 分组 但是“”不应该分组

ResultantList = Group[0] ==> [{1,"a"}
                             {9,"a"}],
                 Group[1] ==>[ {52,"b"),
                               {2,"b"},
                               {88,"b"}] ,
                 // all other items which is "" should be included without groups
                Group[3] [ {40,""}]  
                 Group[4][ {99,""} ] 

我的尝试

var resultantList =  sigList
                    .GroupBy(s => s.SignalGroup)
                    .Select(grp => grp.ToList())
                     //.Where(g => !g.Any(grp => grp.SignalGroup == ""))
                     .ToList();

如上所料

  1. 取消注释 Where 子句仅分组 a 和 b==> 不包含所有具有空值 ( "" ) 的项目

  2. 注释 Where 子句将 a、b 和 "" 字符串组合成一个包含 3 个组(a、b 和 "")的列表。

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    假设第一列类似于独特的Id

    var resultantList =  sigList
        .GroupBy(s => s.SignalGroup == "" ? s.Id.ToString() : s.SignalGroup)
        .Select(grp => grp.ToList())
        .ToList();
    

    因此,如果SignalGroup 是一个空字符串,则GroupBy 采用(唯一)ID,在所有其他情况下采用SignalGroup,因此如果SignalGroup 是@987654327,您将获得每个ID 一组的所需结果@。

    如果不是唯一的,请使用 Guid.NewGuid().ToString() 作为组的键。

    【讨论】:

    • 同样不起作用,在Id的情况下,具有空属性的元素等于另一个元素的相应属性。
    • @Slava Utesinov 我不明白你。我试过var resultantList = sigList .GroupBy(s => s.SignalGroup) .Select(grp => grp.ToList()) .ToList(); ,它对我有用。 ID肯定有一个价值。你是这个意思吗?
    • @jAntoni,使用如下数据尝试此解决方案:{SignalGroup:"", id:1}, {SignalGroup:"1", id:2}
    • @Tim,如果我想按超过 2 个列或字段创建一个组,那么条件是什么?举例来说:如果 SignalGroup 是“”,则按(column1 和 column2)分组,否则如果 SignalGroup 不是“”,则按(column1 和 column2 &column3)分组。我可以在多个列上进行分组,但它期望列的计数相同,但在我的场景中需要分组 -> if then 2-columns else 3-columns like that。这在 LINQ 中可能吗?请帮我解决这个问题
    【解决方案2】:

    在您的示例中,您指定不想分组的项目具有空字符串值。

    您可以指定哪些值不应分组的解决方案:

    static class EnumerableExtensions
    {
        public static IEnumerable<IGrouping<TKey, TSource>> SpecialGroupBy(
            this IEnumerable<TSource> source,
            Func<TSource, TKey> keySelector,
            TKey dontGroupKeyValue)
        {
            // Group all items according to the keySelector,
            // return all groups, except the group with the key dontGroupKeyValue
    
            var groups = source.GroupBy(keySelector);
            foreach (IGrouping<TKey, TSource> group in groups)
            {
                if (group.Key != dontGroupKeyValue)
                {  // return this as a group:
                   return group;
                }
                else
                {   // return every element of the group as a separate IGrouping
                    foreach (TSource element in group)
                    {
                       return Grouping.Create(dontGroupKeySelector, element)'
                    }
                 }
             }
        }
    }
    

    为此,我使用了我找到的帮助器类的改编版here in StackOverFlow。此实现隐藏了 IGrouping 的实际实现。它只公开 IGrouping 所需的属性和函数来创建它。如果您确实需要定期创建 IGrouping,请考虑将其放入某个基础库中。

    public class Grouping<TKey, TElement> : IEnumerable<TElement>, IGrouping<TKey, TElement>
    {
        public static IGrouping<TKey, TElement> Create(TKey key, TElement element)
        {
            return new Grouping<TKey, TElement>()
            {
                Key = key,
                Elements = new TElement[] {element},
            };
        }
        public static IGrouping<TKey, TElement> Create(TKey key,
            IEnumerable<TElement> elements)
        {
            return new Grouping<TKey, TElement>()
            {
                Key = key,
                elements = elements,
            };
        }
    
        private Grouping() { }
    
        public TKey Key { get; private set; }
        private IEnumerable<TElement> elements;
    
        public IEnumerator<TElement> GetEnumerator() => this.elements.GetEnumerator();
        IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
    }
    

    【讨论】:

      【解决方案3】:

      你可以解决你的问题this way,完全没有多余的IdGuid.NewGuid()

      public class Test
      {
          public string property { get; set; }
          public string name { get; set; }
      }
      
      public static void Main()
      {
          var items = new List<Test>()
          {
              new Test{ property = "1", name = "1" },
              new Test{ property = "1", name = "2" },
              new Test{ property = "2", name = "3" },
              new Test{ property = "2", name = "4" },
              new Test{ property = "", name = "5" },
              new Test{ property = "", name = "6" }
          };
      
          var result = items
                  .GroupBy(x => x.property == "")
                  .SelectMany(x =>
                      !x.Key ?
                          x.GroupBy(y => y.property).Select(y => y.ToList()).ToList() 
                          :
                          x.Select(y => new List<Test> { y }).ToList()
                      ).ToList();
      
          foreach (var res in result)
          {
              Console.WriteLine("Group " + res.First().property + ":");
              foreach (var item in res)
                  Console.WriteLine(item.name);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-31
        • 2023-04-08
        • 1970-01-01
        相关资源
        最近更新 更多