Filter over IEnumerable ... .Where?

本文关键字:Where IEnumerable over Filter | 更新日期: 2023-09-27 18:18:27

我编写了一个函数来生成奇数:

static IEnumerable<int> OddNumbers()
{
  int n = 1;
  while (true)
    yield return 1 + 2 * (n++ - 1);
}

我如何浏览和筛选这个列表?我试图删除某个数字factor的所有倍数,我这样写:

using (var oddNumbers = OddNumbers().GetEnumerator())
{
  oddNumbers.MoveNext();
  int factor = oddNumbers.Current;
  yield return factor;
  oddNumbers = oddNumbers.Where(x => x % factor != 0);
}

但是我被告知

The type arguments for method `System.Linq.Enumerable.Where<TSource>(
  this System.Collections.Generic.IEnumerable<TSource>,
  System.Func<TSource,bool>)' cannot be inferred from the usage.
Try specifying the type arguments explicitly`

Filter over IEnumerable ... .Where?

根据我的理解,不需要直接访问枚举数,可以使用Linq单独完成,如下所示:

var FilteredNumbers = OddNumbers().Where(x => x % factor != 0);

您可以使用Linq:

   // Initial generator
   static IEnumerable<int> OddNumbers() {
     for (int n = 1; ; n += 2) // for loop is far better than while here
       yield return n; 
   }  
   ...
   var result = OddNumbers()
     .Where(x => x % factor ! = 0);

修改生成器本身:

   static IEnumerable<int> OddNumbersAdvanced(int factorToExclude = int.MinValue) {
     for (int n = 1; ; n += 2)
       if (n % factorToExclude != 0) 
          yield return n;  
   }  
   ...
   var result = OddNumbersAdvanced(factor);

通过使用foreach循环:

  foreach (int item in result) {
    //TODO: put relevant code here; do not forget to break the loop
  }

由于需要生成幸运数字序列,因此我编写了一些代码来使用迭代器完成此操作。注意,这样做的效率非常低,但希望你这样做只是为了好玩或为了学习

static IEnumerable<int> LuckyNumbers(IEnumerable<int> all = null, int n = 2, int step = 0) {
    if (step == 0) {
        all = Enumerable.Range(1, int.MaxValue); // start with all numbers
        yield return 1;
        step++;
    }            
    // apply a filter for current "n" (starting with 2)
   var filtered = Filtered(all, n);
   // get next item from the sequence (skip items first, because this sequence represents whole lucky number sequence, starting from 1)
    var current = filtered.Skip(step).First();
    yield return current;
    step++;
    // now recursive call back into LuckyNumber
    foreach (var other in LuckyNumbers(filtered, current, step)) {
        yield return other;
    }
}
static IEnumerable<int> Filtered(IEnumerable<int> previous, int n) {
    // filter out each n-th item
    return previous.Where((x, i) => (i + 1)%n != 0);
}

像这样使用:

foreach (var next in LuckyNumbers().Take(10)) {
    Console.WriteLine(next);
}