2016-11-17 6 views
1

Я сделал функцию, чтобы сгенерировать нечетные числа:Фильтровать по IEnumerable .... Где?

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` 
+0

Declare 'oddNumbers' как:' IEnumerable oddNumbers = OddNumbers(); '. Затем используйте другую переменную в 'use' для перечислителя. –

+0

'oddNumbers' является' IEnumerator ', но' Where' требует 'IEnumerable '. Вы можете просто использовать 'OddNumbers(). Где (x => x% factor! = 0)'. – Lee

+0

Uh ... все эти операции кажутся бесконечно бесконечными ... – Nyerguds

ответ

3

В моем понимании нет необходимости доступа к нумератору непосредственно, это можно сделать только с помощью Linq следующим образом.

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

Однако не забудьте применить какой-либо предохранитель на перечислимом, например. Take(), чтобы предотвратить бесконечный цикл, если позже вы перебираете всю коллекцию: foreach, .ToList(). etc ... – LeBaptiste

+0

Я повторно фильтрую коллекцию и хотел бы, чтобы следующий фильтр использовал вывод предыдущего. Есть ли способ отфильтровать коллекцию на месте и сохранить результат? Готовы ли снова фильтроваться? – theonlygusti

1

Вы можете использовать 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 
    } 
+0

Я многократно фильтрую коллекцию и хотел бы, чтобы следующий фильтр использовал вывод предыдущего. Есть ли способ отфильтровать коллекцию на месте и сохранить результат? Готовы ли снова фильтроваться? – theonlygusti

+0

Вы можете * складывать * фильтры: 'var result = OddNumbers(). Где (item => item% factor! = 0) .Where (item => item <100000) .Where (item => (item * item)% 5 == 1); 'просто положить столько' Where' требуется –

+0

бесконечно много ...... конечно, позвольте мне сделать это – theonlygusti

0

Поскольку вам нужно, чтобы генерировать последовательность счастливых чисел, вот какой код я написал для этого с помощью итераторов. Обратите внимание, что это очень неэффективно, чтобы сделать это таким образом, но мы надеемся, что вы делаете это просто для удовольствия или для обучения

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); 
} 
+0

Вы говорите мне, что «это не связано с делимостью на X (так, не связано с коэффициентом x%)», но я вижу в вашем собственном ответе: «Где ((x, i) => (i + 1)% n ! = 0); – theonlygusti

+0

@theonlygusti Ну, в моем ответе я делю не x, а i (индекс элемента в последовательности, а не сам номер). – Evk

+0

Я делаю это в своем самом современном решении. Я ошибся в этом вопросе. – theonlygusti

 Смежные вопросы

  • Нет связанных вопросов^_^