【问题标题】:c# , Linq, Select and Countc#,Linq,选择和计数
【发布时间】:2015-12-19 04:05:13
【问题描述】:

我正在学习 c#。下面的代码打印出 5。我对 Select 的工作原理感到很困惑。结果不应该是 2,因为序列 1 中的第二个和第三个单词比序列 2 中的相应单词短吗?有人可以帮忙解释一下吗?提前谢谢了!

string[] seq1 = { "jumps", "over", "pop", "milk", "egg", }; 
string[] seq2 = { "jam", "dizzy", "fuzzy", "the" };
var count = seq1.Select( n1 => seq2.Where(n2 => n1.Length < n2.Length) ) .Count();

【问题讨论】:

  • 你想让你的代码做什么?您说您希望结果为 2,但从提供的代码中我不知道您要做什么。
  • 不,我不知道,这是我的问题。我对代码的工作方式感到困惑。
  • 谢谢大家的回复。我只是想理解代码..

标签: c# linq select lambda count


【解决方案1】:

您的代码会这样做:

对于后续 1 中的每个项目,选择

seq1.Select( n1 => 

比后续 1 元素短的序列 2 元素的集合。

seq2.Where(n2 => n1.Length < n2.Length)

然后计算您拥有的序列 2 集合的数量(即 5 - 每个序列 1 元素一个)

) .Count();

【讨论】:

  • 不,它只计算来自seq1 的元素。它对 seq2 元素没有任何作用。不超过seq1.Count()
  • 呃,是的。选择为每个序列 1 元素返回序列 2 元素的集合。这个集合很可能是空的,但它仍然是一个被计数的集合。根据您的评论编辑,我们同意它实际上只计算序列 1 元素。
  • seq1 被计算在内,如果你这样做seq1.Select(n1=&gt;n1).Count() 结果是一样的,所有的选择体都是不必要的
  • 我完全同意。我还有什么要说的呢?
  • @wudzik 谢谢!但是如果我将 Select 更改为 SelectMany,为什么结果会变成 8?我的意思是如果它只计算 seq1 ?
【解决方案2】:

没有。使用seq2.Where(n2 =&gt; n1.Length &lt; n2.Length),您可以过滤比较大小的元素,但使用seq1.Select(...),您可以对 seq1 的每个元素执行此操作。有了这个,你会得到一个列表列表。 Select() 函数是投影而不是过滤器。

在您的示例中,这会导致以下结果: `

n1 = "跳跃" => [],

n1 = "over" => ["dizzy", "fuzzy"],

n1 = "pop" => ["dizzy", "fuzzy"],

n1 = "牛奶" => ["头晕", "模糊"],

n1 = "蛋" => ["头晕","模糊"]`

如您所见,您有 5 个元素,每个元素都包含来自 seq2 的部分。

【讨论】:

  • 谢谢!但是如果我将 Select 更改为 SelectMany,则结果变为 8。在这种情况下 .Count 做了什么?
  • 使用 .SelectMany 可以将每个内部结果的所有元素收集到一个列表中。在本例中,这将产生以下列表:["dizzy", "fuzzy", "dizzy", "fuzzy", "dizzy", "fuzzy", "dizzy", "fuzzy"]
  • 我不确定你想要完成什么,但看看这个:seq2.Where(n2 => seq2.Any(n1 => n1.Length
【解决方案3】:

首先,Select 不会像Where 那样过滤输入序列。这就是为什么你得到 5 作为结果。数组 seq1 包含 5 个单词,您正在从该数组中进行选择。选择什么并不重要,因为 - 如前所述 - Select 不会过滤。

你可以用这个:

int count = seq1
    .Where((n1, index1) => seq2.Length > index1 && n1.Length < seq2[index1].Length)
    .Count();

这是使用Zip + Sum 的不同方法:

int count = seq1.Zip(seq2, (n1, n2) => n1.Length < n2.Length ? 1 : 0).Sum();

【讨论】:

    【解决方案4】:

    它计算来自seq1的所有元素(所以它就像seq1.Count()

    这是你的 de-Linq-ued 代码:

    string[] seq1 = { "jumps", "over", "pop", "milk", "egg", };
    string[] seq2 = { "jam", "dizzy", "fuzzy", "the" };
    var count = 0;
    foreach (string n1 in seq1)
    {
        IEnumerable<string> enumerable = seq2.Where(n2 => n1.Length < n2.Length);
        count++;
    }
    

    您的代码 Selects 来自 seq2 的项目比来自 seq 的当前元素短,但对它们没有任何作用。为了实现比较“对应”的项目,你可以运行这个 sn -p

    string[] seq1 = { "jumps", "over", "pop", "milk", "egg", };
    string[] seq2 = { "jam", "dizzy", "fuzzy", "the" };
    
    int count = 0;
    for (int i = 0; i < Math.Min(seq1.Length,seq2.Length); i++)
    {
        if (seq1[i].Length < seq2.Length) count++;
    }
    

    它会检查第二个序列中“对应的”项目是否更长

    编辑:

    更改为 SelectMany 将使其也遍历 seq2

    foreach (string n1 in seq1)
        foreach (string s in seq2.Where(n2 => n1.Length < n2.Length))
            count++;
    

    【讨论】:

    • @user3735871 你可以检查 SelectMany 的 de-linq-ued 代码
    • 我只知道 SelectMany 将列表“展平”。我不知道它是如何遍历 seq2 的。
    猜你喜欢
    • 1970-01-01
    • 2011-09-13
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多