将 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<int>
到 List<int?>
。
简单的解决方案是创建一个新列表并使用foreach
循环添加每个项目,这需要太多时间。
【问题讨论】:
你对太多时间的定义是什么?唯一的方法是循环(使用foreach
或LINQ
)
不是很聪明,但你不能稍微重构你的代码,这样你就不必转换了吗?
Implicit convert List<int?> to List<int>的可能重复
【参考方案1】:
没有比创建新列表更快的方法了:
var newList = list.Select( i => (int?)i ).ToList();
但是使用 LINQ 比使用裸循环要慢。
最快的方法是使用具有预分配容量的List<int?>
:
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<int?>
来自List<int>
。以上是关于将 List<int> 转换为 List<int?> 的最快方法的主要内容,如果未能解决你的问题,请参考以下文章
将 List<int?> 转换为 List<int> 的任何简单方法
无法将 initializer_list 转换为 class<int>