使用linq从C#列表中的每一行获取第n个单词

Nap*_*tor 1 c# linq list

嗨,我有一个多单词字符串的列表。

List<string> myList = new List<string>();
myList.Add("Robert is a bank manager");  
myList.Add("Alice is a cashier");  
myList.Add("Andrew is bank customer");  
Run Code Online (Sandbox Code Playgroud)

现在,对于myList中的每个字符串行,我想获取第n个单词。因此,假设我想从每个字符串中检索偶数个位于数字位置的单词,我希望获得以下输出:

var[] output = {"is", "bank", "is", "cashier", "is", "customer"};
Run Code Online (Sandbox Code Playgroud)

我可以简单地使用for循环并将每个第n个字存储在输出数组中,但很好奇如何使用linq执行相同的操作。

Eri*_*ert 9

我很好奇如何使用LINQ做同样的事情

给某人一条鱼,然后喂它们一天;教他们抓鱼,等等等等。

您需要的是一个用于LINQ验证代码的思考过程。这是我使用的过程。

我要做的第一件事是查看问题的描述,并认为“ 对序列的每个元素执行的操作在哪里?”

对于myList中的每个字符串行,我想获得第n个字。

哦,有一个。

下一个问题是:假设我想对序列中的单个元素执行此操作;我该怎么办? 我可以写一个做到这一点的方法吗?

这个问题似乎可以很好地分解为两个子问题:

1)给定一个字符串,取回一个单词序列。2)给定一个事物序列,每n个事物产生一个序列。

我们知道如何做第一个:那就是Split()

第二个是什么?再一次,我们有一个操作,在操作序列中的每个元素。这次我们正在过滤,因此似乎我们想使用Where

正如其他人指出的那样,您可以Where为此使用一个索引。让我们编写一个辅助方法:

public static IEnumerable<T> TakeEveryNth(
    this IEnumerable<T> items,
    int n,
    int offset = 0) =>
  items.Where((item, i) => (i - offset) % n == 0);
Run Code Online (Sandbox Code Playgroud)

(请注意有关此解决方案的一些信息:其中没有特定于字符串序列的内容,因此我将其设为通用。现在,我们有了一个有用的工具,不仅可以用于单词,而且还可以使用。)

超。让我们将最后两个放在一起:

public static IEnumerable<string> EveryNthWord(
    this string sentence,
    int n,
    int offset = 0) =>
  sentence.Split(" ").TakeEveryNth(n, offset);
Run Code Online (Sandbox Code Playgroud)

好的,我们要对列表中的每个元素执行此操作,然后将结果全部串联在一起。那是SelectMany。因此,解决您的问题的方法是:

public static IEnumerable<string> EveryNthWord(
    this IEnumerable<string> sentences,
    int n,
    int offset = 0) =>
sentences.SelectMany(sentence => sentence.EveryNthWord(n, offset));
Run Code Online (Sandbox Code Playgroud)

现在,我们可以解决您的问题:

var result = sentences.EveryNthWord(2, 1).ToList();
Run Code Online (Sandbox Code Playgroud)

我们完成了。

这就是您尝试提出LINQ解决方案时要通过问题进行推理的方式:将所有内容分解为小块,并为每个块编写一种可以很好地解决一个问题的方法。 然后将它们与查询运算符结合在一起。

如果我们想将所有这些都变成一个表达式怎么办?如果您已经将其拆分,则这样做会容易得多。 只需将它们组合在一起:

var n = 2;
var offset = 1;
var result = sentences
  .SelectMany(sentence => sentence
    .Split(" ")
    .Where((item, i) => (i - offset) % n == 0))
  .ToList();
Run Code Online (Sandbox Code Playgroud)

但是坦率地说,如果将代码分开,代码将更加有用和可读。每种帮助方法都有其自身的用处,因此请保持使用!