将 List<int> 转换为 List<int?> 的最快方法

Posted

技术标签:

【中文标题】将 List<int> 转换为 List<int?> 的最快方法【英文标题】:Fastest way to convert List<int> to List<int?> 【发布时间】:2013-02-17 12:55:40 【问题描述】:

获取原语列表并将其转换为可为空的原语列表的最快方法是什么?例如:List&lt;int&gt;List&lt;int?&gt;

简单的解决方案是创建一个新列表并使用foreach 循环添加每个项目,这需要太多时间。

【问题讨论】:

你对太多时间的定义是什么?唯一的方法是循环(使用foreachLINQ 不是很聪明,但你不能稍微重构你的代码,这样你就不必转换了吗? Implicit convert List<int?> to List<int>的可能重复 【参考方案1】:

没有比创建新列表更快的方法了:

var newList = list.Select( i => (int?)i ).ToList();

但是使用 LINQ 比使用裸循环要慢。

最快的方法是使用具有预分配容量的List&lt;int?&gt;

List<int?> newList = new List<int?>(list.Count); // Allocate enough memory for all items
foreach (var i in list)
    newList.Add(i);

如果您正在寻找列表项的就地类型更改,这是不可能的。

【讨论】:

不使用 LINQ 会更快。 @JeffMercado 实际上,我同意 :-) 我没有测量性能差异,但我想它可以忽略不计。 @Fuex 有趣。我的测试还表明,裸循环比 LINQ(有 1,000,000 个)项目快 30%-40%。 你真的怎么知道迭代项目会胜过Cast方法之类的东西?! :)) 我敢打赌你以前没有测量过! @ArmanEbrahimpour 我测量了?这个答案是 7 年前的。我知道 LINQ 运算符会增加一些开销,但我认为它可以忽略不计。现在我了解了所有开销以及可能消除开销的编译器和运行时优化!请记住,您应该始终在优化之前进行测量!【参考方案2】:

您可以坚持使用Cast LINQ 运算符,而不是Select

List<int> first = new List<int>() 1, 2, 3;
List<int?> second = first.Cast<int?>().ToList();

【讨论】:

Select 你能证明吗? 查看同一问题的其他答案【参考方案3】:

如果你想知道什么是更快的解决方案,你应该通过使用三种不同的方式来做一点benchmark

List<int> list = Enumerable.Range( 0, 10000 ).ToList( );
Stopwatch sw = Stopwatch.StartNew( );

for ( int i = 0; i < 100000; i++ ) 
   List<int?> newList = new List<int?>( );
   foreach( int integer in list )
      newList.Add( ( int? ) integer );


sw.Stop( );
TimeSpan timespan = sw.Elapsed;
Console.WriteLine( String.Format( "Foreach: 0:00:1:00:2:00", timespan.Minutes, timespan.Seconds, timespan.Milliseconds / 10 ) );
sw.Restart( );

for ( int i = 0; i < 100000; i++ )
   List<int?> newList = list.Select( x => ( int? ) x ).ToList( );


sw.Stop( );
timespan = sw.Elapsed;
Console.WriteLine( String.Format( "LINQ-Select: 0:00:1:00:2:00", timespan.Minutes, timespan.Seconds, timespan.Milliseconds / 10 ) );
sw.Restart( );

for ( int i = 0; i < 100000; i++ )
   List<int?> newList = list.Cast<int?>( ).ToList( );


sw.Stop();
timespan = sw.Elapsed;
Console.WriteLine( String.Format( "LINQ-Cast: 0:00:1:00:2:00", timespan.Minutes, timespan.Seconds, timespan.Milliseconds / 10 ) );

结果:

正如我们所料,最好的方法是第一个解决方案 (foreach),这意味着循环遍历元素、强制转换并将它们添加到新列表中。

【讨论】:

您是否尝试过不使用 foreach 并使用简单的“for(i = 0; i ***.com/questions/365615/… 有趣的事实,所以我提供的 SO-Answer 有点过时 ;) 不要忘记在foreach案例中设置列表的Capacity,让它更快更精简。【参考方案4】:

这不是一个新问题,但我目前使用此代码;我分享它,希望它可以帮助其他有同样问题的人: 带有预分配 + Linq 的列表

var branchIds = new List<int?>(branches.Count);
branchIds.AddRange(branches.Select(int.Parse).Select(brId => (int?)brId));

【讨论】:

您没有显示branches 是什么,但由于您使用int.Parse 转换它,它必须是一些string 集合,而问题是如何创建List&lt;int?&gt;来自List&lt;int&gt;

以上是关于将 List<int> 转换为 List<int?> 的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

如何将 List<int> 转换为 string[]?

将 List<int?> 转换为 List<int> 的任何简单方法

将 list<int> 转换为连接的整数字符串?

无法将 initializer_list 转换为 class<int>

是否可以将 MVC C# List<int> 转换为 javascript 数组?

如何使用 dart 将 Uint8list 转换为 List<int>?