tags:

views:

200

answers:

8

Hello. I have some String[] arrays, for example:

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

How can I mix them, so that I get ['a1', 'b1', 'c1', 'a2', 'b2', 'b3', 'b4'] (0 element of a, then b, c, 1 element of a, b, c and so on)? Thanks

More accurately the resulting array must consist of the first value of the first array, then the first value of the second array, ..., the first value of the last array, the second value of the first array, ..., the second value of the last array, ..., the last value of the biggest array. If arrays are not of the same size, the smaller ones just aren't being taken into account.

Here's an illustration:

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)

Also, I'd like to combine variable number of array, not just 3 or 4

A: 
ArrayList al = new ArrayList();
al.Add(array1);
al.Add(array2);
al.Add(array3);

that's probably your best bet, or you will run into ArrayIndexOutOfBound-style problems. You'll probably run into this way too

David
N.B. That won't give the order that the poster wants, though.
Neil Coffey
A: 

For a task like that, I would probably roll my own. I would create a new String[] with the size of the a.length + b.length + c.length and then use an old-fashioned for loop, iterating Math.max(a.length, Math.max(b.length, c.length)) times. Inside the loop, I would add an element from each, testing the index against the length before doing so to avoid bounds exceptions.

It has also been correctly pointed out elsewhere that you would need to keep track of the index of the last item added to the aggregate array.

akf
A: 

If I understand you correctly, you need some function which merges your arrays taking 1 next element from each array if the array has next element.

You'll need to create additional array of indexes (see in example) to track when array has or doesn't have elements to merge:

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;
}
Roman
A: 

From your description (where you need all the 0th elements, then all the 1st, etc, and where the arrays can be of different sizes), then for an easy-to-understand method (but not the most efficient) I would do the following:

  • create a number of Lists each containing the contents of one of the arrays
  • create a List to hold the end result
  • continually cycle through the Lists, removing the 0th element, and adding it to your result List, until none of the lists contain any more elements

You can avoid creating the lists and do things more efficiently by just having an array of indexes that tell you which element you've got up to in each array, but converting to Lists may make the problem easier to conceptualise.

Neil Coffey
A: 
    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];
    }
teehoo
This is plain wrong. You must have an auxiliary variable pointing you to the index you are currently writing to in result.
Petar Minchev
@Petar, Thanks fixed it.
teehoo
+11  A: 
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];
    }
}

UPDATE: more generally

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;
}
Maurice Perry
+1 for varargs ... Now make it a generic method, <T> T[] merge(T[]... arrays) and we're talking ;) well done
basszero
@basszero: yes, that's a good idea
Maurice Perry
@basszero: slight issue though: the creation of an array of a generic type is not allowed.
Maurice Perry
And +1 for using `for( String[] a: arrays )`.
xtofl
@akf think again: the first iterations, j will be incremented three times, then two, then one. The number of iterations actually IS the length of the longest array.
Maurice Perry
+1  A: 
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
I am not a reputation hunter, but why is the down-vote to a, in my opinion, correct code? At least, leave a comment so I know what I have done wrong.
Petar Minchev
+1: Actually, this is the most down-to-earth solution I see in this bunch of high-tech answers.
xtofl
A: 

All the answers above are terrible and can be achieved in 3 statements if one reuses System.arraycopy to build an array big enough to hold all the elements from both arrays. After that use the Array.sort methods to sort this big array passing in a Comparator. There is no need to write your own bubble/merge sort when a perfectly fine one already exists.

mP
Although I agree on the uglyness Idea, sorting doesn't help, since the Comparator you refer to would become hideous. It's a mere 'zip' that's needed...
xtofl
To be honest, I consider your proposition way uglier than the general solution that Maurice Perry posted.
Petar Minchev
Yes sorry i rushed my answer :)
mP