Есть ли способ заполнить коллекцию с помощью выражения LINQ? - PullRequest
3 голосов
/ 09 января 2010

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


Например, допустим, у меня есть следующий код, который работает с диапазоном чисел от одного до десяти:

public static void LinqTest()
{
    List<int> intList = new List<int>();
    for (int i = 1; i <= 10; i++)     //  <==== I'm having to use a for loop
        intList.Add(i);               //        here to populate the List.
    int intSum = intList.Sum();
    int intSumOdds = intList.Where(x => x % 2 == 1).Sum();
    double intAverage = intList.Average();
    Console.WriteLine("Sum is {0}\tSum of Odds is {1}\tAverage is {2}", 
        intSum, intSumOdds, intAverage);
}

LINQ уже заменяет циклы for, которые потребуются для извлечения информации о данных. Мне любопытно, что LINQ можно использовать для замены цикла for, который заполняет данные . Есть ли способ использовать LINQ для замены следующих двух строк кода?

    for (int i = 1; i <= 10; i++)
        intList.Add(i);

Ответы [ 4 ]

4 голосов
/ 09 января 2010

Как уже говорили другие, вы можете использовать Enumerable.Range(int, int) для генерации последовательности целых чисел, возвращаемых как IEnumerable<int>.

И хотя вы можете преобразовать результат в List<int> различными способами, которые уже были предложены, вы должны делать это, только если вам действительно нужен List<T>.

В этом случае нет необходимости делать это. Ваша функция может быть переписана следующим образом:

IEnumerable<int> intList = Enumerable.Range(1, 10);
int intSum = intList.Sum();
int intSumOdds = intList.Where(x => x % 2 == 1).Sum();
double intAverage = intList.Average();

Это более эффективно, так как последовательность, возвращаемая Enumerable.Range, генерируется "лениво" по мере перечисления. С другой стороны, когда последовательность преобразуется в List<int>, все значения должны храниться в памяти одновременно.

4 голосов
/ 09 января 2010

Вы не заполнили бы существующий список LINQ; Вы должны создать Enumerable, а затем преобразовать его в список. В этом случае это так же просто, как

IList<int> intList = Enumerable.Range(1, 10).ToList();
2 голосов
/ 09 января 2010

Я думаю, что вы ищете в конкретном случае Enumerable.Range(). Оттуда, если вы хотите, вы можете отфильтровать список, используя Where s и тому подобное. Например, если бы я хотел, чтобы все числа, у которых степень двойки была меньше 100, я бы сделал что-то вроде Enumerable.Range(1,100).Where(i => i * i < 100). Это очень распространено в функциональных языках, таких как Haskell, где что-то похожее это: filter (\i -> i * i < 100) [1..100]

Конкретный пример замены вашей функции:

Enumerable.Range(1,10).Where(x => x%2 == 1).Sum();
//add separate sum and averages here
0 голосов
/ 09 января 2010

List<T> имеет конструктор, который принимает IEnumerable<T> в качестве параметра. Вы можете использовать Enumerable.Range для генерации чисел.

List<int> values = new List<int>(Enumerable.Range(1, 10));

Если вы хотите добавить значения к ранее построенному List<T>, вы можете использовать List<T>.AddRange таким же образом:

values.AddRange(Enumerable.Range(1, 10));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...