如何在Java中合并两个数组?

6

我有一些String[]数组,例如:

['a1', 'a2']
['b1', 'b2', 'b3', 'b4']
['c1']

我该如何混合它们,以便获得['a1','b1','c1','a2','b2','b3','b4'](先是a的第0个元素,然后是b、c,再是a的第1个元素,然后是b、c,以此类推)?谢谢。
更准确地说,结果数组必须由第一个数组的第一个值、第二个数组的第一个值、...、最后一个数组的第一个值、第一个数组的第二个值、...、最后一个数组的第二个值、...、最大数组的最后一个值组成。如果数组大小不同,则较小的数组不会被考虑在内。
这里有一个示例:
a1 a2 a3 a4
b1 b2 b3 b4 b5 b6 b7
c1 c2
d1 d2 d3 d4 d5

Combines into (brackets are just to highlight steps, so they really mean nothing):
(a1 b1 c1 d1) (a2 b2 c2 d2) (a3 b3 d3) (a4 b4 d4) (b5 d5) (b6) (b7)

此外,我想要合并可变数量的数组,而不仅仅是3或4个。

你能更准确地描述一下它们应该如何混合吗? - Roman
9个回答

17
String result[] = new String[a.length+b.length+c.length];
for (int i = 0, j = 0; j < result.length; ++i) {
    if (i < a.length) {
        result[j++] = a[i];
    }
    if (i < b.length) {
        result[j++] = b[i];
    }
    if (i < c.length) {
        result[j++] = c[i];
    }
}

更新:更加普遍地说

String[] merge(String[]... arrays) {
    int length = 0;
    for (String[] a: arrays) {
        length += a.length;
    }
    String result[] = new String[length];
    for (int i = 0, j = 0; j < length; ++i) {
        for (String[] a: arrays) {
            if (i < a.length) {
                result[j++] = a[i];
            }
        }
    }
    return result;
}

2
+1 对于可变参数... 现在让它成为一个通用方法,<T> T[] merge(T[]... arrays),我们就可以谈论了 ;) 做得好 - basszero
@basszero:不过有一个小问题:不允许创建一个泛型类型的数组。 - Maurice Perry
加一分,因为使用了 for( String[] a: arrays ) - xtofl
@akf 再想一想:在第一次迭代中,j 将增加三次,然后是两次,最后是一次。实际的迭代次数就是最长数组的长度。 - Maurice Perry

1
String[] answer = new String[a.length + b.length + c.length];
int maxLength = Math.max(a.length, Math.max(b.length, c.length));

int counter = 0;    
for (int i = 0; i < maxLength; i++)
{
   if (i < a.length)
      answer[counter++] = a[i];

   if (i < b.length)
      answer[counter++] = b[i];

   if (i < c.length)
      answer[counter++] = c[i];
}

我并不是一个追求声望的人,但为什么要对我认为正确的代码进行负评?至少,请留下一条评论,让我知道我做错了什么。 - Petar Minchev
1
+1:实际上,这是我在这堆高科技答案中看到的最务实的解决方案。 - xtofl

0
为了从两个或更多的数组中实现混合或组合,您需要一个空数组来保存您需要组合或混合的元素。就像这样:
    String[] lines1;
    String[] lines2;
    String[] combined = new String [(lines1.length+lines2.length)];

   for (int i = 0, j = 0; j < combined.length; i++) {
       if (i < lines1.length) {
           combined[j] = lines1[i];
           j++;
       }
       if (i < lines2.length) {
           combined[j] = lines2[i];
           j++;
       }
   }

你可以通过将值分配给combined[j++]来缩短内部条件,因为递增是在之后开始的。


0

如果我理解正确,您需要一些函数来合并您的数组,如果该数组有下一个元素,则从每个数组中取1个下一个元素。

您需要创建索引的附加数组(请参见示例)以跟踪何时数组具有或不具有要合并的元素:

int[] indexes; //should be initialized with 0's 

void int[] mergeArrays(int[] ... arrays) {
   int totalLength = 0;
   for (int[] array : arrays) {
      totalLength += array.length;
   }
   int[] result = new int[totalLength]; 

   indexes = new int[arrays.length];  //array of indexes 
   int mergeIndex = 0;
   while (mergeIndex < totalLength) {
      for (int j = 0; j < arrays.length; j++) {
         if (indexes[j] != -1) {
            changed = true;
            result[mergeIndex++] = arrays[j][indexes[j]];
            indexes[j]++;
            if (arrays[j].length == indexes[j]) {
               indexes[j] = -1;
            } 
         }
      }
   }
   return result;
}

0
针对这样的任务,我可能会自己编写代码。我会创建一个新的String[],大小为a.length + b.length + c.length,然后使用传统的for循环,迭代Math.max(a.length, Math.max(b.length, c.length))次。在循环内部,我会从每个数组中添加一个元素,并在执行此操作之前将索引与长度进行比较,以避免越界异常。

同时,还需要正确地跟踪最后一个添加到聚合数组中的项目的索引。


0
根据您的描述(需要所有第0个元素,然后所有第1个元素等等,并且数组的大小可以不同),为了一个易于理解的方法(但不是最有效的方法),我会执行以下操作:
  • 创建多个列表,每个列表包含一个数组的内容
  • 创建一个列表来保存最终结果
  • 不断循环遍历这些列表,删除第0个元素,并将其添加到结果列表中,直到没有任何列表包含更多元素

您可以避免创建列表并更有效地完成任务,只需拥有一个索引数组即可告诉您在每个数组中已经获取了哪个元素,但转换为列表可能会使问题更容易概念化。


-1
ArrayList al = new ArrayList();
al.Add(array1);
al.Add(array2);
al.Add(array3);

那可能是你最好的选择,否则你会遇到ArrayIndexOutOfBound类型的问题。 你很可能也会遇到这个问题。


1
注意:这并不会按照发帖者想要的顺序排列。 - Neil Coffey

-1
    String[] arr0 = ["a1", "a2"];
    String[] arr1 = ["b1", "b2", "b3", "b4"];
    String[] arr2 = ["c1"];
    int length = arr0.length + arr1.length + arr2.length;
    int max = Math.max(arr0.length, Math.max(arr1.length, arr2.length));
    int index = 0;
    String[] result = new String[length];
    for (int i=0; i<max; i++){
        if (i<arr0.length)
           result[index++] = arr0[i];
        if (i<arr1.length)
           result[index++] = arr1[i];
        if (i<arr2.length)
           result[index++] = arr2[i];
    }

这是完全错误的。你必须有一个辅助变量指向你当前正在写入结果的索引。 - Petar Minchev

-1
所有上面的答案都很糟糕,如果重用System.arraycopy来构建一个足以容纳两个数组中所有元素的大型数组,则可以在3个语句中实现。之后使用Array.sort方法对此大数组进行排序,传递Comparator。当已经存在完全正常的冒泡/归并排序时,没有必要编写自己的排序算法。

尽管我同意这个丑陋的想法,但排序并没有帮助,因为您所提到的比较器会变得丑陋。只需要一个简单的“zip”即可... - xtofl
说实话,我认为你的建议比Maurice Perry发布的通用解决方案要丑陋得多。 - Petar Minchev
是的,抱歉我回答得太仓促了 :) - mP.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接