Create lists from arrays from elements at corresponding indices - java

I am new to java 8. Just wondering how would I do below operation using java 8 streams. Any suggestions
public static void main(String[] args) {
Integer[] arr1 = new Integer[]{1, 2, 3};
Integer[] arr2 = new Integer[]{4, 5, 6};
Integer[] arr3 = new Integer[]{7, 8, 9};
for(int i=0; i<arr1.length; i++){
System.out.println(listFromIndex(arr1[i], arr2[i], arr3[i]));
}
}
private static List<Integer> listFromIndex(Integer e, Integer e1, Integer e2) {
List<Integer> list = new ArrayList<>();
list.add(e) ;
list.add(e1) ;
list.add(e2) ;
return list;
}
Output :
[1, 4, 7]
[2, 5, 8]
[3, 6, 9]

Assuming the arrays are of the same length, you can do it as:
IntStream.range(0, arr1.length)
.mapToObj(i -> listFromIndex(arr1[i], arr2[i], arr3[i]))
.forEach(System.out::println);

If all of the arrays have the same length you can use this:
List<Integer[]> arrays = Arrays.asList(arr1, arr2, arr3);
IntStream.range(0, arr1.length)
.mapToObj(i -> arrays.stream().map(a -> a[i]).collect(Collectors.toList()))
.forEach(System.out::println);
This creates a list containing all arrays. After that it creates a stream iterating over all arrays and collects the new arrays.
This will print the following result:
[1, 4, 7]
[2, 5, 8]
[3, 6, 9]
If you have arrays with different lengths you can use something like this:
Integer[] arr1 = new Integer[]{1, 2, 3};
Integer[] arr2 = new Integer[]{4, 5};
Integer[] arr3 = new Integer[]{7};
List<Integer[]> arrays = Arrays.asList(arr1, arr2, arr3);
IntStream.range(0, arrays.stream().mapToInt(a -> a.length).max().orElseThrow())
.mapToObj(i -> arrays.stream().map(a -> i < a.length ? a[i] : null).collect(Collectors.toList()))
.forEach(System.out::println);
This uses the length of the largest array and checks i before collecting the resulting arrays.
The result will be this:
[1, 4, 7]
[2, 5, null]
[3, null, null]

Related

What is the Java equivalent of Numpy's array_split? [duplicate]

This question already has answers here:
How to split array list into equal parts?
(9 answers)
Efficient way to divide a list into lists of n size
(16 answers)
Java: how can I split an ArrayList in multiple small ArrayLists?
(22 answers)
Closed 4 months ago.
I'd like to split an array into n roughly equal sized chunks, without knowing how large these chunks will be beforehand.
Using Numpy, this can be done with array_split:
>>> import numpy
>>> x = [7, 3, 9, 10, 5, 6, 8, 13]
>>> x
[7, 3, 9, 10, 5, 6, 8, 13]
>>> numpy.array_split(x, 3)
[array([7, 3, 9]), array([10, 5, 6]), array([ 8, 13])]
What's the Java equivalent of doing this? I'm happy to use a library function if available.
If it helps anyone.
#Test
public void testListPartition() {
// Given
Integer[] is = new Integer[] {7, 3, 9, 10, 5, 6, 8, 13};
List<Integer> isList = new ArrayList<Integer>();
Collections.addAll(isList, is);
int nThreads = 3;
int sizeSublist = (int) Math.ceil(isList.size()/(double)nThreads);
List<Integer> truthOne = new ArrayList<Integer>();
Collections.addAll(truthOne, new Integer[] {7, 3, 9});
List<Integer> truthTwo = new ArrayList<Integer>();
Collections.addAll(truthTwo, new Integer[] {10, 5, 6});
List<Integer> truthThree = new ArrayList<Integer>();
Collections.addAll(truthThree, new Integer[] {8, 13});
// When
List<List<Integer>> partitions = Lists.partition(isList, sizeSublist);
// Then
assertEquals(truthOne, partitions.get(0));
assertEquals(truthTwo, partitions.get(1));
assertEquals(truthThree, partitions.get(2));
}
You can split the list using Stream.
static <T> List<List<T>> splitList(List<T> list, int n) {
int size = list.size();
return IntStream.range(0, (size + n - 1) / n)
.map(i -> n * i)
.mapToObj(i -> list.subList(i, Math.min(i + n, size)))
.collect(Collectors.toList());
}
Note that since this uses subList(), each split list shares the original list.
You can split the array as well.
#SuppressWarnings("unchecked")
static <T> T[][] splitArray(T[] array, int n) {
int size = array.length;
return IntStream.range(0, (size + n - 1) / n)
.map(i -> n * i)
.mapToObj(i -> Arrays.copyOfRange(array, i, Math.min(i + n, size)))
.toArray(i -> (T[][])Array.newInstance(array.getClass(), n));
}
However, this cannot be applied to arrays of primitive types.
Separate implementations are required for primitive types.
For example, for int array:
static int[][] splitArray(int[] array, int n) {
int size = array.length;
return IntStream.range(0, (size + n - 1) / n)
.map(i -> n * i)
.mapToObj(i -> Arrays.copyOfRange(array, i, Math.min(i + n, size)))
.toArray(int[][]::new);
}
test:
public static void main(String[] args) {
List<Integer> list = List.of(7, 3, 9, 10, 5, 6, 8, 13);
System.out.println(splitList(list, 3));
Integer[] array = {7, 3, 9, 10, 5, 6, 8, 13};
System.out.println(Arrays.deepToString(splitArray(array, 3)));
int[] ints = {7, 3, 9, 10, 5, 6, 8, 13};
System.out.println(Arrays.deepToString(splitArray(ints, 3)));
}
output:
[[7, 3, 9], [10, 5, 6], [8, 13]]
[[7, 3, 9], [10, 5, 6], [8, 13]]
[[7, 3, 9], [10, 5, 6], [8, 13]]

How to create a new List from merging 3 ArrayLists in round robin style?

I have 3 arrays. I want to merge the 3 arrays and create a new array that shows all the merged integers. I would like this new array to be in round robin style.
Example input:
array = {arr1 = 1, 2, 3, arr2 = 4, 5, 6, arr3 = 7, 8, 9}
Example output:
arr4 = 1, 4, 7, 2, 5, 8, 3, 6, 9
I'm supposed to use this function but I don't understand how can I use a listOfLists:
String roundRobin(List<List<Integer>>listOfLists) {
You could do it more simply using ArrayLists or Arrays.
With Arrays, you create 3 int[] and 1 int[][].
What this translates to is "3 arrays of ints and 1 array of arrays of ints". That is what #4 is: an array of your other arrays. In code it is:
int[]
arr1 = {1, 2, 3},
arr2 = {4, 5, 6},
arr3 = {7, 8, 9};
int[][] arr4 = {arr1, arr2, arr3};
Alternatively, you could use ArrayLists, which differ from Arrays in that you can add or remove elements, among many other actions. The logic is the same in this case, just the syntax is different. You create 3 ArrayList<Integer> and 1 ArrayList<ArrayList<Integer>>, which translates to "3 ArrayLists of Integers and 1 ArrayList of ArrayLists of Integers." In code it is:
ArrayList<Integer>
list1 = new ArrayList<>(Arrays.asList(1, 2, 3)),
list2 = new ArrayList<>(Arrays.asList(4, 5, 6)),
list3 = new ArrayList<>(Arrays.asList(7, 8, 9));
List<ArrayList<Integer>> list4 = new ArrayList<>
(Arrays.asList(list1, list2, list3));
Finally, you can print the output of both methods:
System.out.println("Arrays - int[][]: " + Arrays.deepToString(arr4)
+ "\nLists - List<ArrayList<Integer>>: " + list4);
And you will get:
Arrays - int[][]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Lists - List<List<Integer>>: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Does this help?
You can use two nested for loops:
List<List<Integer>> lists = List.of(
List.of(1, 2),
List.of(3, 4, 5, 6),
List.of(7, 8, 9));
List<Integer> listRobin = new ArrayList<>();
// infinite loop through the columns
for (int i = 0; ; i++) {
// if the maximum number
// of columns is reached
boolean max = true;
// loop through the rows, aka inner lists
for (List<Integer> row : lists) {
// if this column is present
if (i < row.size()) {
// column is present
max = false;
// take value from the column
listRobin.add(row.get(i));
}
}
// while the columns are still present
if (max) break;
}
// output
System.out.println(listRobin);
// [1, 3, 7, 2, 4, 8, 5, 9, 6]
See also: Filling a jagged 2d array first by columns
I think just loop input and get element and add element to a list of array is easy to understand.
public static List<Integer> roundRobin(List<List<Integer>> listOfLists) {
if (listOfLists == null || listOfLists.isEmpty()) {
return new ArrayList<>();
}
int maxLength = -1;
for (List<Integer> list : listOfLists) {
if (list.size() > maxLength) {
maxLength = list.size();
}
}
List<Integer> result = new ArrayList<>(maxLength * listOfLists.size());
for (int i = 0; i < maxLength; i++) {
for (List<Integer> list : listOfLists) {
if (i < list.size()) {
result.add(list.get(i));
}
}
}
return result;
}
To populate a 1d list from the columns of a 2d list, you can use two nested streams: first by columns, and then by rows. The length of the internal lists does not matter, in an outer stream you can traverse while the columns are still present.
List<List<Integer>> listOfLists = List.of(
List.of(1, 2, 3, 4),
List.of(5, 6),
List.of(7, 8, 9));
List<Integer> listRobin = IntStream
// infinite Stream through
// the columns of a 2d list
.iterate(0, i -> i + 1)
// take the values from the column
// Stream<List<Integer>>
.mapToObj(i -> listOfLists
// iterate over the inner lists
.stream()
// take those lists where
// this column is present
.filter(list -> list.size() > i)
// take value from the column
.map(list -> list.get(i))
// return a new list
.collect(Collectors.toList()))
// while the columns are still present
.takeWhile(list -> list.size() > 0)
// flatten to a single stream
// Stream<Integer>
.flatMap(List::stream)
// return a new list
.collect(Collectors.toList());
// output
System.out.print(listRobin); // [1, 5, 7, 2, 6, 8, 3, 9, 4]
See also: Efficient way to choose data from several Lists with round robin algorithm

How to store subarrays of different size into a single 2d array

I’m trying to store 1d array of different size into a 2d array and then sort the 2d array based on the sum of subarray.
Try this.
int[][] arrays = {{0, 1, 2, 3}, {4}, {5, 6}, {7},};
int[][] sorted = Arrays.stream(arrays)
.map(a -> new Object() {
int sum = IntStream.of(a).sum();
int[] array = a;
})
.sorted(Comparator.comparing(obj -> obj.sum))
.map(obj -> obj.array)
.toArray(int[][]::new);
System.out.println(Arrays.deepToString(sorted));
output
[[4], [0, 1, 2, 3], [7], [5, 6]]

Java: Sort an Array Based on the Index Order of Another Array

In Java, how can I sort an array based on the index order of another sorted array? For instance, if I have:
arr1 = {26, 8, 3}
arr2 = {3, 1, 2}
arr3 = {57, 23, 11}
arr4 = {78, 2, 61}
and I sort arr2 in ascending order to be
arr2 = {1, 2, 3}
and I want the other to then be:
arr1 = {8, 3, 26}
arr3 = {23, 11, 57}
arr4 = {2, 61, 78}
How can I accomplish this is Java? I know I would save the new sorted arrays into new instances. Anything helps, thanks!
Found answer elsewhere
public class SortTogether{
// sort the array a, and also update the elements in array b, c, and d
// based on the index of a
public static void bubbleSort(int[] a, int[] b, int[] c, int[] d) {
for(int i=0; i<a.length; i++){
for(int j=0; j<a.length-i-1;j++){
if(a[j]>a[j+1]){
// when you are swapping the elements
int t = a[j]; a[j]=a[j+1];a[j+1]=t;
// swap the elements in the other arrays as well
// so the elements in other array will also stay together
t = b[j]; b[j]=b[j+1];b[j+1]=t;
t = c[j]; c[j]=c[j+1];c[j+1]=t;
t = d[j]; d[j]=d[j+1];d[j+1]=t;
}
}
}
}
public static void main(String a[]) {
int[] arr1 = {26, 8, 3};
int[] arr2 = {3, 1, 2};
int[] arr3 = {57, 23, 11};
int[] arr4 = {78, 2, 61};
System.out.println("Before sort");
display(arr1);
display(arr2);
display(arr3);
display(arr4);
bubbleSort(arr2,arr1,arr3,arr4);
System.out.println("\nAfter sort");
display(arr1);
display(arr2);
display(arr3);
display(arr4);
}
public static void display(int[] arr) {
for (int num : arr) System.out.printf("%4d", num);
System.out.println();
}
}
Here is one way to do it.
sort the indices of the target array based on the arrays contents.
then use that index array to map all the arrays based on the indexed one.
Integer[] indices = IntStream.range(0, arr2.length)
.boxed()
.sorted(Comparator.comparing(i -> arr2[i]))
.toArray(Integer[]::new);
List<int[]> list = Stream
.of(arr1, arr2, arr3, arr4).map(arr -> Stream
.of(indices)
.mapToInt(i -> arr[i])
.toArray())
.collect(Collectors.toList());
list.forEach(arr -> System.out.println(Arrays.toString(arr)));
Prints
[8, 3, 26]
[1, 2, 3]
[23, 11, 57]
[2, 61, 78]
You could also place the arrays in another "2D" array and do as follow with the same result.
int[][] arrays = { arr1, arr2, arr3, arr4 };
List<int[]> list = Arrays
.stream(arrays)
.map(arr -> Stream
.of(indices)
.mapToInt(i -> arr[i])
.toArray())
.collect(Collectors.toList());

Flatmapping a 2D array by column rather than row in Java

Given the following two dimensional array
int[][] arr = {{1, 2}, {3, 4}, {5, 6}};
How can I flatten it column-by-column using the Java 8 Stream API? I want to get:
int[] result = {1, 3, 5, 2, 4, 6};
I tried doing a simple flatMap, but this flattens row-by-row and results in the wrong order:
// result is { 1, 2, 3, 4, 5, 6 }
int[] result = Arrays.stream(arr)
.flatMapToInt(Arrays::stream)
.toArray();
I considered transposing the array first so that I can use the above snippet, but creating an intermediate, transposed copy of the array seems unnecessary. How can I flatmap by column directly?
It can be assumed that all the nested arrays are of same length.
You can stream the inner indexes and flatMap to each outer array:
IntStream.range(0, arr[0].length)
.flatMap(i -> Arrays.stream(arr).mapToInt(a -> a[i]))
.toArray()
If we assume that all the nested arrays are of the same length we can use nested loops:
int[][] arr = {{1, 2}, {3, 4}, {5, 6}};
int[] res = new int[arr.length * arr[0].length];
int j = 0;
for (int i = 0; i < arr[0].length; i++) {
for (int[] a : arr) {
res[j++] = a[i];
}
}
System.out.println(Arrays.toString(res)); // [1, 3, 5, 2, 4, 6]
This is another way to do it:
int[][] nestedArray = {{1, 12, 2}, {1, 13, 11, 5, 16}, {7, 8, 9}};
LinkedList<Integer> theList = new LinkedList<>();
for(int[] sList: nestedArray) {
stream(sList)
.forEach(theList::add);
}
theList.stream()
.forEach(e ->System.out.println(e));
I revised the previous code to more KISS and readable.
int[][] nestedArray = {{3, 4, 5, 6}, {1, 2}, {7, 8, 9}};
LinkedList<Integer> theList = new LinkedList<>();
for(int[] sList: nestedArray) {
stream(sList)
.forEach(theList::add);
}
theList.stream()
.forEach(e ->System.out.println(e));

Categories