C#将List<int>转换为List<double>

35

我有一个 List<int>,我想将其转换为 List<double>。除了遍历 List<int> 并添加到新的 List<double> 中之外,还有其他方法吗:

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]));
}

有没有一种高级的方法可以做到这一点?我正在使用C# 4.0,因此答案可能利用了新的语言特性。

1
(仅供参考,注意C# 4.0的差异性不能在具体类型(List<T>)上工作,不能在列表通常情况下(IList<T>)工作,并且不能在intdouble之间工作) - Marc Gravell
6个回答

64

你可以像其他人建议的那样使用Select,但你也可以使用ConvertAll

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

这有两个优点:

  • 它不需要使用LINQ,因此如果您正在使用.NET 2.0并且不想使用LINQBridge,您仍然可以使用它。
  • 它更高效:由于ToList方法不知道Select的结果大小,因此它可能需要在进行过程中重新分配缓冲区。而ConvertAll则知道源和目标大小,因此可以一次性完成所有操作,而且无需迭代器的抽象。

缺点:

  • 它只适用于List<T>和数组。如果您得到了一个普通的IEnumerable<T>,则必须使用SelectToList
  • 如果您的项目中大量使用LINQ,则保持在此处继续使用也许更加一致。

1
并且在.NET 3.5中可用 - Mitch Wheat
1
ConvertAll只是LINQ表达式的包装器吗? - Filip Ekberg
除了更清楚地显示您的意图之外,Select 有什么区别吗? - VVS
@Filip,@VVS:请看“优点”中的第二点。想象一下有一个包含一百万条目的列表-ConvertAll可以创建一个包含一百万条目的新列表开始,但Select(...).ToList(...)不能-它将不得不保持可调整大小的缓冲区。 - Jon Skeet
@Marc:确实。海报提到了.NET 4.0,所以我有点认为他对.NET 2.0不感兴趣。 - Mitch Wheat

42

您可以使用LINQ方法:

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

另外,列表类有一个 ForEach 方法:

List<double> doubles = new List<double>(integers.Count);
integers.ForEach(i => doubles.Add(i));

这需要使用Select<int,double>(i => i).ToList();有没有办法使用“Type”变量而不是int来使用<,>语法? - Ames
1
@Chris:通常情况下,使用integers.Select(i => (double)i)是惯用的方式。但是,泛型是编译时特性 - 如果您想要使用仅在执行时已知的类型,则需要使用反射。C# 4中的动态类型可能能够帮助您解决这个问题,但在我们确定之前,您必须给出更具体的示例。 - Jon Skeet
使用第二个演示,我可以创建一个类型为double的反射列表,然后使用foreach语句从基于int的列表中添加项目。升级将发生并且一切都会很顺利。这个回答实际上解决了我的问题,但是上面的回答更加简洁地回答了我提出的问题。 - Ames

8
您可以使用Select扩展方法来实现此功能:
List<double> doubleList = intList.Select(x => (double)x).ToList();

那么,不使用循环有意义吗?从性能上讲呢? - Ames
@Chris:使用Select和ToList不会更有效率。ConvertAll 可能 会更好 - 你可以避免Add内部的检查开销,但是调用委托的开销也会增加。你有证据表明这段代码对你来说是瓶颈吗? - Jon Skeet
没有任何证据。在我的应用程序中,“double”示例将是动态的,因此如果没有反射,进行强制转换就很困难。我只是想知道是否有一些我不知道的整洁的 lambda 函数或类似的东西来处理强制转换。 - Ames
@Chris:你可以构建一个表达式树来执行转换,很可能会这样做。然而,在那一点上,你已经有了一个稍微不同的问题。 - Jon Skeet
我可以使用反射。我的问题已经解决了。最终,我只是使用了foreach,并将其添加到动态反射生成的<whatever>列表中。感谢您的帮助。 - Ames

2
您可以使用方法组:
lstDouble = lstInt.Select(Convert.ToDouble)

2
您可以在 .Net Framework 2.0 中使用 ConvertAll 方法,这里是一个示例:
        List<int> lstInt = new List<int>(new int[] { 1, 2, 3 });
        List<double> lstDouble = lstInt.ConvertAll<double>(delegate(int p)
        {
            return (double)p;
        });

0

你可以使用Select或ConvertAll。请记住,ConvertAll也适用于.Net 2.0


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接