Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 转换IEnumerable<;int>;不带ToArray()的to int[]_C#_Ienumerable_Toarray - Fatal编程技术网

C# 转换IEnumerable<;int>;不带ToArray()的to int[]

C# 转换IEnumerable<;int>;不带ToArray()的to int[],c#,ienumerable,toarray,C#,Ienumerable,Toarray,没有ToArray(),如何将IEnumerable转换为int[]?我需要一个比ToArray()更快的方法或函数。 我有一个大的int质量状态和两个小的左右质量状态,使用方法的Take和Skip。代码: int[] left = state.Take(pivot).ToArray(); int[] right = state.Skip(pivot).ToArray(); pivot-拆分点。这在很大程度上取决于IEnumerable后面的实际类型。如果它已经是一个数组,则可以对其进行施

没有
ToArray()
,如何将
IEnumerable
转换为
int[]
?我需要一个比
ToArray()
更快的方法或函数。 我有一个大的int质量状态和两个小的左右质量状态,使用方法的Take和Skip。代码:

 int[] left = state.Take(pivot).ToArray();
 int[] right = state.Skip(pivot).ToArray();

pivot-拆分点。

这在很大程度上取决于IEnumerable后面的实际类型。如果它已经是一个数组,则可以对其进行施放。如果是其他的,通常除了
ToArray()
之外,没有其他方法。你可能想考虑为什么它是缓慢的。下面可能有一个LINQ查询执行数据库调用,可以对其进行优化。从
IEnumerable
获取
int[]
有四种可能的方法。按速度顺序:

  • 它已经是一个
    int[]
    ,请将其回滚
  • 它是一种集合类型,具有自己的
    Count
    CopyTo
    ,请使用它
  • 它是一种类型,您可以找到其大小,分配该大小的数组,并通过迭代源来填充它
  • 分配一个数组,填充它,但如果到达末尾,则重新分配一个新数组并进行复制。继续执行此操作直到完成,然后根据需要修剪阵列
  • Linq的
    ToArray()
    将不执行第一个操作,因为
    ToArray()
    旨在保护源不受
    ToArray()
    结果更改的影响

    在其余的选项中,Linq尝试选择最快的选项。因此,你不会有太大的进步

    如果您可以接受对阵列进行铸造,则您将能够使用以下内容覆盖该情况:

    int[] array = intEnum as int[] ?? intEnum.ToArray();
    
    (如果您知道
    intEnum
    始终是一个数组,那么您可以直接执行强制转换。相反,如果您知道
    intEnum
    从来都不是数组,那么上面的操作就更慢,因为它总是有尝试的成本,而没有实现该方法的好处)

    否则,您将无法做得更好,除非您知道可枚举的大小,但它不是一个
    ICollection
    ,所以linq无法找到它本身

    编辑

    问题补充了一条评论:


    我有一个大整数数组。通过使用Take和Skip的方法,我把它分成两大块

    如果您使用的是.NET Core,则此案例在上个月合并到祝福存储库中的提交时已经过优化,因此如果您使用最新版本的corefx或等待更新,则您已经对此进行了优化

    否则,您可以应用与Linq版本相同的逻辑:

    让我们调用源数组
    sourceArray

    我们有一个像
    var en=sourceArray.Skip(amountSkipped).Take(amounttake)这样的
    IEnumerable

    如果
    amountSkipped
    amounttake
    小于零,则此处应使用零。如果省略了
    Skip()
    ,则应将零用于
    amountSkipped
    。如果省略了
    Take()
    ,则应将
    int.MaxValue
    用于
    amounttake

    输出阵列的大小为:

    int count = Math.Min(sourceArray.Length - amountSkipped, amountTaken);
    
    然后,我们可以创建并分配给阵列:

    int[] array = new int[count];
    int index = 0;
    foreach (int item in en)
      array[index] = item;
    
    现在将填充
    数组
    ,而无需分配和修剪,从而大致节省
    日志计数
    分配。这确实会更快

    不过,如果您使用的是最新的corefx,那么这已经为您完成了,并进一步优化了避免枚举器分配的功能

    尽管如此,如果所做的只是
    跳过
    接受
    ,那么您可以完全放弃它,直接操作:

    int count = Math.Min(sourceArray.Length - amountSkipped, amountTaken);
    int[] array = new int[count];
    Array.Copy(sourceArray, amountSkipped, array, 0, count);
    
    根本不需要
    Skip()
    Take()

    再次编辑

    现在的问题是:

    int[] left = state.Take(pivot).ToArray();
    int[] right = state.Skip(pivot).ToArray();
    
    我们可以简单地做到:

    int leftCount = Math.Min(state.Length, Math.Max(pivot, 0));
    int[] left = new int[leftCount];
    Array.Copy(state, 0, left, 0, leftCount);
    
    int rightCount = Math.Min(state.Length - leftCount);
    int[] right = new int[rightCount];
    Array.Copy(state, leftCount, right, 0, rightCount);
    
    这确实是一个相当大的进步

    如果我们知道
    pivot
    介于0和
    state.Length
    之间,那么我们可以使用更简单的:

    int[] left = new int[pivot];
    Array.Copy(state, 0, left, 0, pivot);
    
    int[] right = new int[state.Length - pivot];
    Array.Copy(state, pivot, right, 0, state.Length - pivot);
    

    如果你给它更多的信息,你只能更快地得到它。您有比简单的
    IEnumerable
    更多的信息吗?所以人们可以用它来重现这个问题并给出更好的答案。我使用ToArray()可以在大约240毫秒内将一个1000万整数的枚举转换成一个数组。这还不够快吗?是否还有其他问题导致它花费这么长时间?@Andersforgren
    但仅仅因为一个问题不好并不意味着它值得否决票。
    事实上,这正是它的意思。问题需要不仅仅是“清晰”的,而是适当的、高质量的问题。问题确实需要明确,但它们不仅仅需要明确。除此之外,它们还需要进行充分的研究、合理的范围、主题和有用性。“我有一个大的int数组。通过方法的Take和Skip,我将它分为两个大数组”。把它放在问题中,它会有很大的改进。2和3基本上不一样吗?或者至少
    ToArray
    没有专门处理3种情况。它要么是一个
    ICollection
    ,要么是2,否则就是4。@juharr在3中我的意思是通过迭代,而不是通过
    CopyTo
    ToArray()
    在当前.NET核心版本中始终处理2和4,并处理3,包括ILST上的
    Select()
    等情况(它可以通过在源代码列表上执行
    Count
    来找到大小,但必须实现
    CopyTo
    本身)。