【问题标题】:c# A better way to Copy/Merge multiple arrays into one arrayc#将多个数组复制/合并到一个数组中的更好方法
【发布时间】:2018-04-29 11:59:25
【问题描述】:

谁能建议是否有更好的方法将多个数组复制到一个数组中?生成的数组必须具有相同顺序的元素,例如首先是 arrayOne 值,然后是 arraySecond 值,等等。

以下是我当前正在执行的按预期工作的模型。正在寻找一种更智能的方法。

// Initialise the first array.
string[] arrayOne = new string[5];
arrayOne[0] = "arrayOneValue[0]";
arrayOne[1] = "arrayOneValue[1]";
arrayOne[2] = "arrayOneValue[2]";
arrayOne[3] = "arrayOneValue[3]";
arrayOne[4] = "arrayOneValue[4]";

// Initialise the second array.
string[] arrayTwo = new string[6];
arrayTwo[0] = "arrayTwoValue[0]";
arrayTwo[1] = "arrayTwoValue[1]";
arrayTwo[2] = "arrayTwoValue[2]";
arrayTwo[3] = "arrayTwoValue[3]";
arrayTwo[4] = "arrayTwoValue[4]";
arrayTwo[5] = "arrayTwoValue[5]";

// Initialise the third array.
string[] arrayThree = new string[3];
arrayThree[0] = "arrayThreeValue[0]";
arrayThree[1] = "arrayThreeValue[1]";
arrayThree[2] = "arrayThreeValue[2]";

// string[] arrayN = new string[n]
//.
//.
//.

// Initialise the target array.
string[] finalArray = new string[arrayOne.Length + arrayTwo.Length + arrayThree.Length];
// ArrayN - string[] finalArray = new string[arrayOne.Length + arrayTwo.Length + arrayThree.Length + arrayN.Length];

// Copy/merge the three arrays into the target array.
Array.Copy(arrayOne, 0, finalArray, 0, arrayOne.Length);
Array.Copy(arrayTwo, 0, finalArray, arrayOne.Length, arrayTwo.Length);
Array.Copy(arrayThree, 0, finalArray, (arrayOne.Length + arrayTwo.Length), arrayThree.Length);
//.
//.
//.
//.
// ArrayN - Array.Copy(arrayN, 0, finalArray, (arrayOne.Length + arrayTwo.Length + arrayN), arrayN.Length) ?;

如您所见,arrayN 的代码可能会更长。我最多尝试将 5 个数组复制到一个数组中,因此它是可管理的。我将这种技术用作 WebAPI 的一部分,其中一组 oracle 参数对象根据业务规则进行合并,以传递给多个 Oracle 存储过程。任何建议在这里表示赞赏。提前致谢。 结果

Console output 
/*--- Destination array -
arrayOneValue[0]
arrayOneValue[1]
arrayOneValue[2]
arrayOneValue[3]
arrayOneValue[4]
arrayTwoValue[0]
arrayTwoValue[1]
arrayTwoValue[2]
arrayTwoValue[3]
arrayTwoValue[4]
arrayTwoValue[5]
arrayThreeValue[0]
arrayThreeValue[1]
arrayThreeValue[2]*/

【问题讨论】:

    标签: c# arrays


    【解决方案1】:

    您可以只使用 LINQ .Concat,这样您就不需要手动处理数组长度和偏移量:

    var finalArray = arrayOne.Concat(arrayTwo).Concat(arrayThree).ToArray();
    

    它的性能可能比使用Array.Copy 稍差,但这段代码更易读、更易维护且更安全,这一点更重要。

    【讨论】:

    • 谢谢!优雅的解决方案。我最终采用了这种方法。
    【解决方案2】:

    您可以将输入数组放在一个集合中并对其进行迭代。我只提到这一点是因为这可能比使用 LINQ 更有效。这取决于您正在处理的数据,但可能不足以产生影响。

    在下面的代码中,在我的机器上,LINQ 需要 9000-13000 个滴答声(一个滴答声 = 100 ns),而调用 Array.Copy 大约是 500 个滴答声。

    public static void Benchmark1()
    {
        var arr1 = Enumerable.Range(1,10000).ToArray();
        var arr2 = Enumerable.Range(10001,20000).ToArray();
        var arr3 = Enumerable.Range(20001,30000).ToArray();
        var arr4 = Enumerable.Range(30001,40000).ToArray();
    
        var sw = Stopwatch.StartNew();
        var result = arr1.Concat(arr2).Concat(arr3).Concat(arr4).ToArray();
        sw.Stop();
        Console.WriteLine($"Elpased ticks: {sw.ElapsedTicks}");
    }
    
    public static void Benchmark2()
    {
        var arr1 = Enumerable.Range(1,10000).ToArray();
        var arr2 = Enumerable.Range(10001,20000).ToArray();
        var arr3 = Enumerable.Range(20001,30000).ToArray();
        var arr4 = Enumerable.Range(30001,40000).ToArray();
    
        var arrays = new List<int[]>() {arr1, arr2, arr3, arr4};
    
        var sw = Stopwatch.StartNew();
    
        int finalLen = 0;
        foreach (var arr in arrays)
        {
            finalLen += arr.Length;
        }
    
        var result = new int[finalLen];
        int currentPosition = 0;
    
        foreach (var arr in arrays)
        {
            Array.Copy(arr, 0, result, currentPosition, arr.Length);
            currentPosition += arr.Length;
        }
    
        sw.Stop();
        Console.WriteLine($"Elpased ticks: {sw.ElapsedTicks}");
    }
    

    【讨论】:

    • 谢谢。很棒的信息!当然,要考虑多次出现和更大的数组。在我的用例中,浪费的时间可以忽略不计,但请记住。
    【解决方案3】:

    通过预先创建一个大数组,然后使用Array.Copy,我们可以实现非常合理的连接速度,即使是非常多的数组:

    public static T[] ConcatArrays<T>(params T[][] p)
    {
        var position = 0;
        var outputArray = new T[p.Sum(a => a.Length)];
        foreach (var curr in p)
        {
            Array.Copy(curr, 0, outputArray, position, curr.Length);
            position += curr.Length;
        }
        return outputArray;
    }
    

    所以,现在我们可以:

    string bigArray = ConcatArrays(arrayOne, arrayTwo, arrayThree)
    

    string[][] arrays = new[]{arrayOne, arrayTwo, arrayThree};
    string bigArray = ConcatArrays(arrays);
    

    【讨论】:

    • 很有趣,谢谢,BurnsBA 所关心的和 Yeldar Kurmangaliyev 的解决方案都是最好的。我会在某个阶段试一试。
    【解决方案4】:

    你必须使用数组吗?使用列表和 AddRange()。如果您最终需要一个数组,那么最后只需调用 ToArray()。

    【讨论】:

    • 谢谢,这实际上是一种可能性。更多的代码重构,但可能是值得的。
    【解决方案5】:
    var one =  new [] { arrayOne, arrayTwo, arrayThree }.SelectMany(x => x);
    

    【讨论】:

      猜你喜欢
      • 2021-06-11
      • 2018-02-28
      • 2017-01-11
      • 2011-04-16
      • 1970-01-01
      • 2014-04-27
      • 1970-01-01
      • 2022-01-23
      • 2019-03-14
      相关资源
      最近更新 更多