c#将多个数组复制/合并到一个数组中的更好方法

Posted

技术标签:

【中文标题】c#将多个数组复制/合并到一个数组中的更好方法【英文标题】:c# A better way to Copy/Merge multiple arrays into one array 【发布时间】: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]*/

【问题讨论】:

【参考方案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);

【讨论】:

以上是关于c#将多个数组复制/合并到一个数组中的更好方法的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中组合两个或多个字节数组的最佳方法

我可以在 C# 中的一行中编辑多个数组值吗

什么时候 ArrayList 比在 C# 中使用数组更有效? [复制]

从 C# 中的字节数组中删除尾随空值

vue合并两个对象

js将数组中一个或多个字段相同的子元素中合并