views:

236

answers:

4

One of the great things about LINQ is that allows you to get information that's related to a collection without having to manually write code to iterate through the collection. Is there a way to use LINQ to populate a collection, thus avoiding the need to write a loop?


For example, let's say I have the following code which works with a range of numbers from one to ten:

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 is already replacing the for loops that would be required to retrieve information about the data. I'm curious as if LINQ could be used to replace the for loop that populates data. Is there a way to use LINQ to replace the following two lines of code?

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

You wouldn't fill an existing list with LINQ; you'd create an Enumerable and then convert it to a list. In this case, it's as simple as

IList<int> intList = Enumerable.Range(1, 10).ToList();
Isaac Cambron
+1 Nice, but you are off by one if you want to match the example in the question. int i = 1; i <= 10; i++
Jason Rowe
er, right. fixed
Isaac Cambron
+1 good answer. little remark: The runtime does exactly the same, maybe a little bit faster because it's natively compiled. Well, with the JIT-compiler that's not even sure.
Atmocreations
The `Enumerable` class is part of `System.Linq`, so does that mean we're still using LINQ?
Ben McCormack
Well, LINQ is really two things: a set of methods for generating and working with enumerables, and a special syntax for using those methods. In this case, we're using the former but not the latter. I think you probably do `(from Enumerable.Range(1, 10)).ToList()` if you want to use the special syntax, though I don't see the advantage.
Isaac Cambron
+2  A: 

I think what you're looking for in the specific case is Enumerable.Range(). From there, if you want to you can filter the list by using Wheres and such. For instance, if i wanted all the numbers from whose power of two is below 100 i'd do something like Enumerable.Range(1,100).Where(i => i * i < 100). This is very common in functional languages like Haskell where something similar is this: filter (\i -> i * i < 100) [1..100]

A specific example to replace your function:

Enumerable.Range(1,10).Where(x => x%2 == 1).Sum();
//add separate sum and averages here
RCIX
That makes sense. I wasn't sure at the time if Sum needed a bunch of params if it wasn't a list though.
RCIX
A: 

List<T> has a constructor that takes an IEnumerable<T> as a parameter. You can use Enumerable.Range to generate the numbers.

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

If you want to add the values to a previously constructed List<T>, you can use List<T>.AddRange in the same way:

values.AddRange(Enumerable.Range(1, 10));
280Z28
+3  A: 

As the others have said, you can use Enumerable.Range(int, int) to generate a sequence of integers returned as IEnumerable<int>.

And while you can convert the result to a List<int> in the various ways that have been suggested already, you should only do that if you actually need a List<T>.

In this case, there is no need to do so. Your function could be rewritten as follows:

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

This is more efficient since the sequence returned by Enumerable.Range is generated "lazily" as it is enumerated. On the other hand, when the sequence is converted to a List<int> then all of the values must be held in memory at once.

Nick Guerrera
+1 for avoiding using List<int> in favour of IEnumerable<int>
Anton