为什么SelectMany()不将字符串[]展平为字符[]

本文关键字:字符 字符串 SelectMany 为什么 | 更新日期: 2023-09-27 18:21:06

我只是想了解linq是如何工作的,并尝试不同的方法来测试Count()GroupBy()SelectMany()。我被困在一个场景中,我不明白为什么SelectMany()没有将string[]类型扁平化为char类型。

这是代码:

string s = "A quick brown fox jumps over the lazy dog".ToLower();
char[] arratchar = s.ToCharArray();
var data= arratchar.GroupBy(x=>x).Select(y=> new {Alphabet = y.Key,Count = y.Count()});

这将完美地返回字符串中的字母计数。

当我这样做时,它会返回a:的计数

string s = "A quick brown fox jumps over the lazy dog".ToLower();
var countofA = s.Count(x => x == 'a');

但现在我正在尝试测试SelectMany(),我知道它会在集合中压平集合,但在这种情况下它不起作用,下面是我写的代码:

string[] s = "A quick brown fox jumps over the lazy dog".ToLower().Split(' ') ;
var res = s.Select(x => x == "quick"); // this works
var re1s = s.SelectMany(x => x == 'q'); // but this not even compiles

为什么SelectMany()不将字符串[]展平为字符[]

SelectMany签名:

public static IEnumerable<TResult> SelectMany<TSource, TResult>(
    this IEnumerable<TSource> source,
    Func<TSource, IEnumerable<TResult>> selector
)

正如您所看到的,SelectMany(reffer)期望Func<TSource, IEnumerable<TResult>>作为选择器——选择器的返回值必须是IEnumerable实现。在第一种情况下,Select期望任何值(Func<TSource, TResult>):x == "quick"评估值true/false,因此结果将是可枚举的boolIEnumerable<bool>)。不幸的是,bool不可分配给IEnumerable——这就是它不编译的原因。

x == "quick"是一个布尔表达式,因此当您调用s.Select(x => x == "quick")时,它将返回IEnumerable<bool>

出于同样的原因,s.SelectMany(x => x == "quick")不会编译。因为它需要一个返回CCD_ 22的函数。显然,bool没有实现IEnumerable<T>,所以它不进行编译。

我相信你对SelectMany有一些误解。SelectMany用于扁平化某些数据结构。它应该返回IEnumerable<T>,而不是Boolean。看看它的签名。

public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector);

它取Func<TSource, IEnumerable<TResult>>,意味着它取一个以TSource为参数的函数,并且必须返回IEnumerable<TResult>

假设你有List<List<int>>,它有一些列表,所有列表都包含3个整数。如果您想将List<List<int>>展平为包含所有9个整数的单个List<int>,那么您将使用SelectMany

List<int> list1 = new List<int> {1, 2, 3};
List<int> list2 = new List<int> { 4, 5, 6 };
List<int> list3 = new List<int> { 7, 8, 9 };
List<List<int>> lists = new List<List<int>>
{
    list1,
    list2,
    list3
};
List<int> flatList = lists.SelectMany(x => x).ToList();
//flatList will contain numbers 1-9

下面展示了使用selectmany可以执行的操作。假设你有一个句子单词列表作为一个字符数组,你想知道使用了什么字符:

List<char[]> sentence = "A quick brown fox jumps over the lazy dog"
    .ToLower().Split(' ').Select(o=>o.ToCharArray()).ToList();
List<char> characters = sentence.SelectMany(x => x).ToList(); 

注意List<char[]>是如何被平坦化为List<char>的。