Linq查询从多个List <string> </string>中选择单个字符串

时间:2014-05-23 16:59:39

标签: c# string linq

我很难理解为什么我会得到我的结果。

我有两个字符串列表:

var list1 = new List<String> {"item 1", "item 2"};
var list2 = new List<String> { "item 3", "item 4" };

版本1 - 输出:“第2项”

var item =
            from x in (list1.Concat(list2))
            where x.EndsWith("2")
            select x;

        Console.WriteLine(item.First());

第2版 - 输出:“i”

var item =
            from x in (list1.Concat(list2))
            where x.EndsWith("2")
            select x.First();

        Console.WriteLine(item.First());

版本3 - 输出:“System.Linq.Enumerable + WhereEnumerableIterator`1 [System.String]”

var item =
            from x in (list1.Concat(list2))
            where x.EndsWith("2")
            select x;

        Console.WriteLine(item);

鉴于版本2输出“i”,我希望版本3输出“第2项”。为什么会出现这种情况?

6 个答案:

答案 0 :(得分:5)

在版本3中,select x返回与您的critera匹配的序列字符串;它恰好是一个包含一个项目的序列。

无论您传入任何内容,

Console.WriteLine都会内部调用.ToString()。由于IEnumerable<T>没有有意义的字符串表示形式,因此.NET中的默认值是打印该类型的字符串名称。

根据你的措辞,我认为你的混淆部分来自于误解为什么版本2的工作方式。在版本2中,select x.First()实际上有点奇怪/巧合,因为字符串 IEnumerable<char>,因此您可以对字符串执行LINQ操作。对于符合条件的每个结果,.First()会返回该char序列的第一个元素。所以你要说:

  

&#34;对于符合我标准的每个元素,选择第一个字符,然后返回匹配的所有第一个字符的序列。&#34;

事实上,版本2中的itemIEnumerable<char>,其中包含一个元素。在Console.WriteLine()上拨打IEnumerable<char>只会按顺序打印字符。所以你得到了&#34;我&#34;。

(注意:我在回答此问题后看到,问题已被编辑,以便在投影内部和结果中调用.First(),因此有关将IEnumerable<char>传递给Console.WriteLine的问题并非如此。 #39; t完全相关了)

请记住,LINQ几乎是关于使用集合,直到您明确地减少它们为止。例如,Select只是一个投影或转换。它返回传递给它的相同数量的项目,进行转换。 Where减少了集合,但它仍然是一套。

答案 1 :(得分:2)

您的版本2正在从字符串x.First()中选择第一项/字符,而您的第一个版本是从结果集中选择第一项 - &gt;第一串。

版本1类似于 - 从结果集中选择第一个项目

var item =  (from x in (list1.Concat(list2))
            where x.EndsWith("2")
            select x).First(); //First complete string will be selected

和版本2类似 - 从结果集中的字符串中选择第一项

var item =  from x in (list1.Concat(list2))
            where x.EndsWith("2")
            select x.First(); //only first char will be selected for string

您的第三种情况是选择IEnumerable<string>,因此当您致电Console.WriteLine时,它会调用ToString的默认实施,从而获得

  

“System.Linq.Enumerable + WhereEnumerableIterator`1 [System.String]”

答案 2 :(得分:0)

使用First()时,您正在实现列表,导致迭代器执行。这是急切的执行。你的第三个版本使用的select没有实现列表abd使用返回迭代器的Defeered Execution,因此在它上面调用ToString()返回迭代器名称

答案 3 :(得分:0)

因为Where会返回IEnumerable

你写的相当于:

var whoKnows = list1.Concat(list2).Where(x => x.EndsWith("2"));
Console.WriteLine(whoKnows);

集合的ToString只返回类名。

答案 4 :(得分:0)

版本2中x的类型为String。版本1中item的类型是IEnumerable。

因此,您的版本2返回一个字符列表,这些字符是每个字符串的第一个字符。在版本1中,item.First()返回结果集的第一个元素,即字符串。

答案 5 :(得分:0)

//This raise a exception if no item found
var item=list1.Concat(list2).First(i => i.EndsWith("2"));
//this return default value (null) if no item found
var item2 = list1.Concat(list2).FirstOrDefault(i => i.EndsWith("2"));