tags:

views:

701

answers:

5

I have a List<int> and I want to convert it to a List<double>. Is there any way to do this other than just looping through the List<int> and adding to a new List<double> like so:

List<int> lstInt = new List<int>(new int[] {1,2,3});
List<double> lstDouble = new List<double>(lstInt.Count);//Either Count or Length, I don't remember

for (int i = 0; i < lstInt.Count; i++)
{
    lstDouble.Add(Convert.ToDouble(lstInt[0]));
}

Is there a fancy way to do this? I'm using C# 4.0, so the answer may take advantage of the new language features.

+7  A: 

You could do this using the Select extension method:

List<double> doubleList = intList.Select(x => (double)x).ToList();
Darin Dimitrov
+1 very concise, and still readable.
Matt Ellen
but still just a loop under the covers, right?
Mitch Wheat
@Mitch Wheat, that is correct.
Alastair Pitts
So is there any point in not just using a loop? Performance wise?
Ames
@Chris: Using Select and ToList won't be more efficient. ConvertAll *might* be - you lose the overhead of the checks within Add, but there's the overhead of calling a delegate that many times. Do you have evidence that this code is a bottleneck for you?
Jon Skeet
No evidence at all. In my application the "double" example will be dynamic so casting is difficult to do without reflection. I was just wondering if there was some neat lamba function or something that I didn't know about that took care of casting so to speak.
Ames
@Chris: You could build an expression tree to perform the conversion, quite possibly. However, at that point you've got a somewhat different question.
Jon Skeet
I can just use reflection. I've got my problem solved. I ended just doing a foreach and adding to a dynamic reflection generated list of <whatever>. Thanks for the help.
Ames
+9  A: 

You can use LINQ methods:

List<double> doubles = integers.Select<int, double>(i => i).ToList();

or:

List<double> doubles = integers.Select(i => (double)i).ToList();

Also, the list class has a ForEach method:

List<double> doubles = new List<double>(integers.Count);
integers.ForEach(i => doubles.Add(i));
Guffa
This needs to be Select<int,double>(i => i).ToList(); Is there a way to use the <,> syntax with a 'Type' variable instead of int?
Ames
@Chris: It would actually normally just be `integers.Select(i => (double)i)` to be idiomatic. But no, generics are a compile-time feature - if you want to use a type only known at execution time, you'll need to use reflection. Dynamic typing in C# 4 may be able to help you with that, but you'd have to give a more concrete example before we could say for sure.
Jon Skeet
Using the second demo, I can create a reflection list of type double, then use the foreach stuff to add items from the int based list. Promotion will occur and everything happy will happen. This response actually solved my problem, but the ones above are more concise to the question I asked.
Ames
+31  A: 

You can use Select as suggested by others, but you can also use ConvertAll:

List<double> doubleList = intList.ConvertAll(x => (double)x);

This has two advantages:

  • It doesn't require LINQ, so if you're using .NET 2.0 and don't want to use LINQBridge, you can still use it.
  • It's more efficient: the ToList method doesn't know the size of the result of Select, so it may need to reallocate buffers as it goes. ConvertAll knows the source and destination size, so it can do it all in one go. It can also do so without the abstraction of iterators.

The disadvantages:

  • It only works with List<T> and arrays. If you get a plain IEnumerable<T> you'll have to use Select and ToList.
  • If you're using LINQ heavily in your project, it may be more consistent to keep using it here as well.
Jon Skeet
and available in .NET 3.5 as well
Mitch Wheat
Isn't ConvertAll just a wrapper for the LINQ expression?
Filip Ekberg
Is there a difference to Select except that it's more clearly showing your intention?
VVS
@Filip, @VVS: See the second point in "advantages". Imagine a list with a million entries - ConvertAll can create a new list with a million entries to start with, but Select(...).ToList(...) can't - it will have to keep a resizable buffer.
Jon Skeet
@Mitch - available in .NET 2.0...
Marc Gravell
@Marc: indeed. The poster mentioned .NET 4.0, so I kinda assumed he wasn't interested in .NET 2.0.
Mitch Wheat
A: 

You can use Select or ConvertAll. Keep in mind that ConvertAll is available in .Net 2.0 too

Giorgi
+2  A: 

You can use ConvertAll method inside of .Net Framework 2.0 here is an example

        List<int> lstInt = new List<int>(new int[] { 1, 2, 3 });
        List<double> lstDouble = lstInt.ConvertAll<double>(delegate(int p)
        {
            return (double)p;
        });
fyasar