首页 > 解决方案 > 这个表达式在 GroupBy 方法中是什么意思?

问题描述

bool test = anyCollection.GroupBy(x => "AnyKeyString").Any(g => g.Count() > 1);

此 Lambda 将始终返回 true,我认为这意味着“将占位符 x 设为 true(因为字符串本身始终为 true??),并按集合中为 true 的任何事物分组”

我的问题是为什么我在 GroupBy 中放一个字符串总是返回 true?

我不太确定,当我在集合中找到重复值时,我受到了启发,下面是示例:

    public class Alphabet
    {
      public int ID { get; set; }
      public string Initial { get; set; }
    }

        List<Alphabet> testList = new List<Alphabet>()
        {
            new Alphabet() { ID = 1, Initial = "A"},
            new Alphabet() { ID = 2, Initial = "B"},
            new Alphabet() { ID = 3, Initial = "C"},
            new Alphabet() { ID = 4, Initial = "D"},
        };

        List<Alphabet> testList2 = new List<Alphabet>()
        {
            new Alphabet() { ID = 1, Initial = "A"},
            new Alphabet() { ID = 2, Initial = "A"},
            new Alphabet() { ID = 3, Initial = "C"},
            new Alphabet() { ID = 4, Initial = "C"},
        };

        bool test1 = testList.GroupBy(x => x.Initial).Any(g => g.Count() > 1);
        // false
        bool test2 = testList2.GroupBy(x => x.Initial).Any(g => g.Count() > 1);
        // true
        bool test3 = testList2.GroupBy(x => "Initial").Any(g => g.Count() > 1);
        // true

有点跑题了,我怎么能按通用类型列表分组?

    List<string> testList = new List<string>(){
        "A",
        "B",
        "C",
        "D"
    };

    List<string> testList2 = new List<string>(){
        "A",
        "A",
        "C",
        "D"
    };

    var k = testList.GroupBy(x => ????).Any(g => g.Count() > 1);
    var c = testList2.GroupBy(x => "A").Any(g => g.Count() > 1);
    // always true

标签: c#linq

解决方案


.GroupBy不是过滤器 - 它不是.Where. .GroupBy需要一个键选择器Func<TObject, TKey>

所以如果你有这样的功能(相当于x => x.Initial):

public string GetGroupKeyForObject(Alphabet alpha)
{
    return alpha.Initial;
}

可以传递为:.GroupBy(GetGroupKeyForObject)

然后它将按初始分组。但是如果你有这样的功能(相当于x => "anystring"):

public string GetGroupKeyForObject(Alphabet alpha)
{
    return "anystring";
}

然后将确定所有项目都具有键“anystring”以进行分组。

如果您只想选择初始为“anystring”的项目,您应该这样做:

bool result = testList.Where(a => a.Initial == "anystring").Count() > 1;

或者更高效(但可读性较差):

bool result = testList.Where(a => a.Initial == "anystring").Skip(1).Any();

假设你有这个测试集:

字母(为简洁起见仅显示 Initial,但与您的对象相同):["A", "A","B", "B", "B", "B","C","D","E","F"]

你按 Initial 分组,你会得到 6 个组:

键:组项目

A:["A", "A"]

乙:["B", "B", "B", "B"]

C:["C"]

丁:["D"]

E:["E"]

F:["F"]

但是,如果您按“anystring”对其进行分组,您将获得 1 个组:

键:组项目

任意字符串:["A", "A","B", "B", "B", "B","C","D","E","F"]

因此.Any(x => x.Count() > 1),在第一个示例上执行,将返回,true因为 A 和 B 的计数高于 1。在第二个示例上执行相同的操作与调用.Count() > 1原始集合相同,因为您将整个选择按静态值分组,所以你只会得到一组。


推荐阅读