如果条件满足,则将C#Linq分组到列表中不分组

时间:2017-09-01 10:46:08

标签: c# linq

我有一个清单
我的要求

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

  

即在某种情况下我希望将其分组   否则不应该分组

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

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

例如

  

列表=   [{1,""},{40,"&#34),{9""},{52," B&#34 ),{2" b"},{99,"&#34),{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和"")。

3 个答案:

答案 0 :(得分:2)

假设第一列类似于唯一的Id

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

因此,如果SignalGroup为空字符串,GroupBy将获取(唯一)ID,在所有其他情况下为SignalGroup,因此您可以获得每个ID所需的一个组的结果SignalGroup""

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

答案 1 :(得分:0)

您可以解决问题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);
    }
}

答案 2 :(得分:0)

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

一种解决方案,您可以指定不应对哪些值进行分组:

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();
}