I have three arrays like the below: int a[] = {1,2,3,4}; int b[] = {5,6,7,8}; int c[] = {9,10,11,12};
I want to merge above arrays to get the below result: int d[] = {1,5,9,2,6,10,3,7,11,4,8,12};
I have coded it as below but it is concatenated:
public class MergeTwoArrays2 {
public static void main(String[] args)
{
int a[] = {1,2,3,4};
int b[] = {5,6,7,8};
int c[] = {9,10,11,12};
int a1 = a.length;
int b1 = b.length;
int c1 = c.length;
int d1 = a1 b1 c1;
int[] d = new int[d1];
for (int i = 0; i < a1; i = i 1) {
d[i] = a[i];
}
for (int i = 0; i < b1; i = i 1) {
d[a1 i] = b[i];
}
for (int i = 0; i < c1; i = i 1) {
d[a1 b1 i] = c[i];
}
for (int i = 0; i < d1; i = i 1) {
System.out.println(d[i]);
}
}
}
OUTPUT: [1,2,3,4,5,6,7,8,9,10,11,12]
Expected Output:
[1,5,9,2,6,10,3,7,11,4,8,12]
CodePudding user response:
So you want to take the first element from all three arrays a
, b
, c
, then the second one, and so on.
For that, you need a different strategy of populating the array d
.
You can iterate over all your arrays simultaneously checking if the next element exists in a particular array, and if it's the case assigning it to the current position in the resulting array.
int[] d = new int[d1];
for (int i = 0, j = 0; i < Math.max(Math.max(a1, b1), c1);i ) {
if (i < a1) d[j ] = a[i];
if (i < b1) d[j ] = b[i];
if (i < c1) d[j ] = c[i];
}
System.out.println(Arrays.toString(d));
Output:
[1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]
In the case when all the given arrays a
, b
, c
are of the same length, you can get rid of the if
-statements:
for (int i = 0, j = 0; i < a1; i ) {
d[j ] = a[i];
d[j ] = b[i];
d[j ] = c[i];
}
Generalizing the problem
Your problem can be generalized to merging an arbitrary number of integer arrays having the same length.
That would allow eliminating duplicated statements and hard-coded names.
/**
* Merges arbitrary number of arrays of the same length
*/
public static int[] joinAll(int[]... arrays) {
if (arrays.length == 0) return new int[0];
int[] result = new int[arrays.length * arrays[0].length];
for (int i = 0, j = 0; i < arrays[0].length; i ) {
for (int[] arr: arrays) {
result[j ] = arr[i];
}
}
return result;
}
System.out.println(Arrays.toString(joinAll(a, b, c)));
Output:
[1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]
Stream-based solution
In case if you fill comfortable with Stream IPA you represent the logic from generalized method shown above using a single statement:
/**
* Merges arbitrary number of arrays of the same length
*/
public static int[] joinAll(int[]... arrays) {
if (arrays.length == 0) return new int[0];
return IntStream.range(0, arrays[0].length)
.flatMap(i -> Arrays.stream(arrays).mapToInt(arr -> arr[i]))
.toArray();
}
CodePudding user response:
With java streams you can do that in that way:
var aMap = IntStream.range(0, a.length)
.boxed()
.collect(Collectors.toMap(i -> i, i -> a[i], (x, y) -> y));
var bMap = IntStream.range(0, b.length)
.boxed()
.collect(Collectors.toMap(i -> i, i -> b[i], (x, y) -> y));
var cMap = IntStream.range(0, c.length)
.boxed()
.collect(Collectors.toMap(i -> i, i -> c[i], (x, y) -> y));
var collect = Stream.of(aMap, bMap, cMap)
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey))
.values().stream()
.flatMap(Collection::stream).map(Map.Entry::getValue).toList();