I'm trying to add the elements of two two-dimensional arrays with each other, by using the java stream API.
I managed the problem with a one-dimensional array, but I don't know how to proceed further with a two-dimensional array.
Here is the code to transform:
public static int[][] add(final int[][] m1, final int[][] m2) {
int[][] e = new int[m2.length][m2[0].length];
for (int i = 0; i < m1.length; i++) {
for (int j = 0; j < m1[i].length; j++) {
e[i][j] = m1[i][j] + m2[i][j];
}
}
return e;
}
And this is the code which I wrote for the same purpose but only with a one-dimensional array:
public static int[] addOneDimension(final int[] a, final int b[]) {
int[] c = IntStream.range(0, a.length)
.map(i -> a[i] + b[i])
.toArray();
return c;
}
In particular, I don't know how to use the map() method on two-dimensional arrays.
This can be implemented using IntStream and its methods mapToObj to handle rows and map to handle elements in each row:
static int[][] add(int[][] a, int [][] b) {
return IntStream.range(0, a.length)
.mapToObj(i -> add(a[i], b[i])) // int[] is object
.toArray(int[][]::new); // create new 2D array
}
static int[] add(int[] a, int[] b) {
return IntStream.range(0, a.length)
.map(i -> a[i] + b[i]) // processing int operands
.toArray(); // IntStream.toArray() returns int[]
}
Test
int[][] a = {
{1, 2},
{3, 4}
};
int[][] b = {
{10, 20},
{30, 40}
};
System.out.println("Sum of a + b = ");
Arrays.stream(add(a, b))
.map(Arrays::toString)
.forEach(System.out::println);
Output
Sum of a + b =
[11, 22]
[33, 44]
Single-method implementation may be as follows:
static int[][] add2D(int[][] a, int [][] b) {
return IntStream
.range(0, a.length)
.mapToObj(i -> IntStream
.range(0, a[i].length)
.map(j -> a[i][j] + b[i][j])
.toArray()
)
.toArray(int[][]::new);
}
You can use Stream#reduce method to sum the elements of two or more 2d arrays:
public static int[][] sumArrays(int[][]... arrays) {
// reduce the stream of arrays into a single
// array by sequentially summing array pairs
return Arrays.stream(arrays).reduce((a1, a2) -> IntStream
// iterate over the indices of
// the rows of the largest array
.range(0, Math.max(a1.length, a2.length))
.mapToObj(i -> IntStream
// iterate over the indices of
// the cells of the largest row
.range(0, Math.max(
i < a1.length ? a1[i].length : 0,
i < a2.length ? a2[i].length : 0))
// sum the elements of two rows if exist, or 0 otherwise
.map(j -> (i < a1.length && j < a1[i].length ? a1[i][j] : 0)
+ (i < a2.length && j < a2[i].length ? a2[i][j] : 0))
.toArray())
.toArray(int[][]::new))
.orElse(null);
}
// test
public static void main(String[] args) {
int[][] arr1 = {
{1},
{1, 1}};
int[][] arr2 = {
{2},
{2, 2},
{2, 2, 2}};
int[][] arr3 = {
{3, 3, 3, 3},
{3, 3, 3, 3},
{3, 3, 3, 3},
{3, 3, 3, 3}};
int[][] sum = sumArrays(arr1, arr2, arr3);
// output
Arrays.stream(sum).map(Arrays::toString).forEach(System.out::println);
//[6, 3, 3, 3]
//[6, 6, 3, 3]
//[5, 5, 5, 3]
//[3, 3, 3, 3]
}
See also: Sum of 2 different 2d arrays
Related
i'm tring to return an array that have all number have been rebeated less than N times.
expected output : 1,4
this is my cod :
-- Main --
int[] data = {1, 2, 2, 3, 3, 3, 4, 5, 5};
int n = 1;
Solution.solution(data, n);
-- class Solution --
public static int[] solution(int[] data, int n) {
int l = data.length, count = 0;
int[] Narr = new int[l];
for(int i =0 ; i < l; i++){
count = 0;
for(int j=1 ; j < l ; j++){
if(data[i] == data[j]){
count++;
}
if(j == l-1){
if(count < n){
Narr[i] = data[i];
System.out.println(Narr[i]);
}
}
}
}
return Narr;
}
I would break this down to multiple steps.
First lets create a countMap that holds track of all the occurrences:
int[] data = {1, 2, 2, 3, 3, 3, 4, 5, 5};
int n = 1;
Map<Integer, Long> countMap = Arrays.stream(data).boxed()
.collect(Collectors.groupingBy(s -> s, Collectors.counting()));
System.out.println(countMap); // {1=1, 2=2, 3=3, 4=1, 5=2}
Now all we need to do is to check for the condition count <= n:
List<Integer> resultList = new ArrayList<>();
countMap.forEach((integer, count) -> {
if (count <= n) resultList.add(integer);
});
System.out.println(resultList); // [1, 4]
And last but not least converting the list back to array:
// {1, 4}
int[] resultArray = resultList.stream()
.mapToInt(Integer::intValue)
.toArray();
I have a 2d-array data, as an example I choose those numbers:
int[][] data = {
{1, 2, 3, 4},
{1, 2, 3, 4},
{1, 2, 3, 4}};
For each column I want to add the sum of numbers together and save them in seperate integers.
This is the result im looking for:
c_zero = 3;
c_one = 6;
c_two = 9;
c_three = 12;
This is the code I have thus far:
int c_zero = 0;
int c_one = 0;
int c_two = 0;
int c_three = 0;
for (int a = 0; a < data.length; a++) {
for (int b = 0; b < data.length; b++) {
for (int[] row : data)
for (int value : row) {
if (int[] row == 0) { //this does not work
c_zero += value;
}
if (int[] row == 1) { //this does not work
c_one += value;
}
...
}
}
}
How can I get the values for each row in a specific row?
I would create a 1D integer array and use that to store the running sum for each column:
int[][] data = {{1,2,3,4},
{1,2,3,4},
{1,2,3,4}};
int[] colSums = new int[data[0].length];
for (int r=0; r < data.length; ++r) {
for (int c=0; c < data[r].length; ++c) {
colSums[c] += data[r][c];
}
}
System.out.println(Arrays.toString(colSums)); // [3, 6, 9, 12]
Using Java 8, you can apply the reduce method to the stream over the rows of a 2d array to sum the elements in the columns and produce a 1d array of sums.
// array must not be rectangular
int[][] data = {
{1, 2, 3, 4},
{1, 2, 3, 4},
{1, 2, 3, 4, 5}};
int[] sum = Arrays.stream(data)
// sequentially summation of
// the elements of two rows
.reduce((row1, row2) -> IntStream
// iterating over the indexes of the largest row
.range(0, Math.max(row1.length, row2.length))
// sum the elements, if any, or 0 otherwise
.map(i -> (i < row1.length ? row1[i] : 0)
+ (i < row2.length ? row2[i] : 0))
// array of sums by column
.toArray())
.orElse(null);
// output of an array of sums
System.out.println(Arrays.toString(sum));
// [3, 6, 9, 12, 5]
// output by columns
IntStream.range(0, sum.length)
.mapToObj(i -> "Column " + i + " sum: " + sum[i])
.forEach(System.out::println);
//Column 0 sum: 3
//Column 1 sum: 6
//Column 2 sum: 9
//Column 3 sum: 12
//Column 4 sum: 5
See also:
• Adding up all the elements of each column in a 2d array
• How to create all permutations of tuples without mixing them?
I have managed to create both arrays, however I can't figure out how to combine the two arrays. Every tutorial I see merges them as such:
int[] arr1 = {3, 3, 5, 6, 8, 9};
int[] arr2 = {3, 4, 5, 6};
// Output: 3, 4, 5, 6, 8, 9
What I need is something that would output: 3, 3, 3, 4, 5, 5, 6, 6, 8, 9
Here is the code I have written so far:
import java.util.Scanner;
public class Merger {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int[] arr1 = new int[10000];
int[] arr2 = new int[10000];
int[] merged = new int[20000];
int a1 = 0;
int a2 = 0;
int size = -1;
int size2 = -1;
int sizecheck = 0;
int size2check = 0;
System.out
.println("Enter the values for the first array, up to 10,000 values, enter a negative number to quit");
for (int i = 0; i < arr1.length; i++) {
arr1[i] = scan.nextInt();
merged[i] = arr1[i];
if (arr1[i] <= 0) {
break;
}
if (size <= arr1[i]) {
size = arr1[i];
sizecheck++;
}
a1++;
}
System.out
.println("Enter the values for the second array, up to 10,000 values, enter a negative number to quit");
for (int i = 0; i < arr2.length; i++) {
arr2[i] = scan.nextInt();
merged[i + a1] = arr2[i];
if (arr2[i] <= 0) {
break;
}
if (size2 <= arr2[i]) {
size2 = arr2[i];
size2check++;
}
a2++;
}
System.out.println("First Array: ");
for (int i = 0; i < a1; i++) {
System.out.print(" " + arr1[i]);
}
System.out.println("\nSecond Array: ");
for (int i = 0; i < a2; i++) {
System.out.print(" " + arr2[i]);
}
}
}
This prints both arrays out, however does not combine and sort the two.
Here's the code ! There may be a faster/easier way to do it but this one works as long as the 2 arrays are sorted
public static void main(String[] args) {
int[] a1 = {1, 2, 3, 5};
int[] a2 = {1, 3, 4, 4, 4, 5};
int[] a3 = merge(a1, a2);
for (int i : a3) {
System.out.print(i);
}
}
public static int[] merge(int[] a1, int[] a2) {
int[] a3 = new int[a1.length + a2.length];
int indexA1 = 0;
int indexA2 = 0;
for (int i = 0; i < a3.length; i++) {
int n;
if (indexA1 == a1.length && indexA2 < a2.length) {
n = a2[indexA2];
indexA2++;
} else if (indexA1 < a1.length && indexA2 == a2.length) {
n = a1[indexA1];
indexA1++;
} else {
if (a1[indexA1] < a2[indexA2]) {
n = a1[indexA1];
indexA1++;
} else {
n = a2[indexA2];
indexA2++;
}
}
a3[i] = n;
}
return a3;
}
I assume that you are not yet familiar with Streams, but I would like to give you an example of what you can do with them.
Add import
import java.util.stream.IntStream;
Add this at the end of your main method
System.out.println("");
IntStream arr1Stream = IntStream.of(arr1).limit(a1); //creates an InStream with the first a1 values of arr1
IntStream arr2Stream = IntStream.of(arr2).limit(a2);
int[] both = IntStream.concat(arr1Stream, arr2Stream).sorted().toArray(); //combines the two streams, sorts them an converts them to an Array
System.out.println(Arrays.toString(both)); //easy way to print an array
The easiest way is to use a Stream.
int[] arr1 = {3, 3, 5, 6, 8, 9};
int[] arr2 = {3, 4, 5, 6};
Stream both arrays.
flatMap them to a single IntStream
sort them
convert to an array
int [] combined = Stream.of(arr1,arr2)
.flatMapToInt(Arrays::stream)
.sorted()
.toArray();
System.out.println(Arrays.toString(combined));
Prints
[3, 3, 3, 4, 5, 5, 6, 6, 8, 9]
A non-stream approach can be done as follows:
// increase arr1 to make room for arr2
int oldLen = arr1.length;
arr1 = Arrays.copyOf(arr1, arr1.length+arr2.length);
// copy arr2 starting at 0, to arr1 starting at the old length
// positon of arr1 for a length of arr2
System.arraycopy(arr2, 0, arr1, oldLen, arr2.length);
// sort and print
Arrays.sort(arr1);
System.out.println(Arrays.toString(arr1));
Prints
[3, 3, 3, 4, 5, 5, 6, 6, 8, 9]
Although your question, as asked, said nothing about merging sorted arrays, here is how you would do it.
The algorithm is simple. Just iterate thru each array and compare current values.
if arr1[i] <= arr2[k], copy arr1[i] to result, advance i by 1
else copy arr2[k] to result, advance k by 1.
in all cases the index to result, r, is advanced by 1
public int[] merge(int[] arr1, int[] arr2) {
// result array
int[] result = new int[arr1.length + arr2.length];
int r = 0;
int k = 0;
int i = 0;
// Iterate thru the arrays, copying the lowest or equal value
// to the target array. This process will cease when one of the arrays
// has been fully processed.
for (; i < arr1.length && k < arr2.length; ) {
for (; k < arr2.length && i < arr1.length;) {
if (arr1[i] <= arr2[k]) {
result[r++] = arr1[i++];
}else {
result[r++] = arr2[k++];
}
}
}
Having reached this far in the algorithm, one of the arrays must have been completely processed. So try and copy both. For the empty array, the while loop basically acts like an if statement.
while (i < arr1.length) {
result[r++] = arr1[i++];
}
while (k < arr2.length) {
result[r++] = arr2[k++];
}
// return the result
return result;
}
public class Merger {
public static void main(String[] args) {
int[] arr1 = { 3, 3, 5, 6, 8, 9 };
int[] arr2 = { 3, 4, 5, 6 };
int[] res = merge(arr1, arr2);
System.out.println(Arrays.toString(res));
}
public static int[] merge(int[] arr1, int[] arr2) {
int[] res = new int[arr1.length + arr2.length];
for (int i = 0, a1 = 0, a2 = 0; i < res.length; i++) {
if (a1 == arr1.length)
res[i] = arr2[a2++];
else if (a2 == arr2.length)
res[i] = arr1[a1++];
else
res[i] = arr1[a1] <= arr2[a2] ? arr1[a1++] : arr2[a2++];
}
return res;
}
}
A simple solution can be written using the classes, Arrays and System.
Steps:
Copy elements of arr1[] into a new array (say, output[]) whose size is the sum of the sizes of the given arrays.
Copy the elements of arr2[], after the element of arr1[], into output[]
Sort output[]
Demo:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] arr1 = { 3, 3, 5, 6, 8, 9 };
int[] arr2 = { 3, 4, 5, 6 };
// Copy elements of arr1[] into a new array whose size is the sum of the sizes
// of the given arrays
int[] output = Arrays.copyOf(arr1, arr1.length + arr2.length);
// Copy the elements of arr2[], after the element of arr1[], into output[]
System.arraycopy(arr2.clone(), 0, output, arr1.length, arr2.length);
// Sort output[]
Arrays.sort(output);
// Display output[]
System.out.println(Arrays.toString(output));
}
}
Output:
[3, 3, 3, 4, 5, 5, 6, 6, 8, 9]
You can use System.arraycopy method for this purpose:
int[] arr1 = {3, 3, 5, 6, 8, 9};
int[] arr2 = {3, 4, 5, 6};
// create a new array of total length
int[] arr3 = new int[arr1.length + arr2.length];
// copy first array to the beginning of the total array
System.arraycopy(arr1, 0, arr3, 0, arr1.length);
// copy second array to the end of the total array
System.arraycopy(arr2, 0, arr3, arr1.length, arr2.length);
// sort the total array
Arrays.sort(arr3);
System.out.println(Arrays.toString(arr3));
// [3, 3, 3, 4, 5, 5, 6, 6, 8, 9]
Hey everyone I am a beginner and I am trying to do this problem, here is what I have tried so far...I am really stumped though:
Write a method called int[] arrayUnion(int[] a, int[] b) that, given two int arrays, returns a new array with unique elements from a and b. No duplicates!
Example Outputs:
arrayUnion([1, 2, 3], [-1, 0, 1]) returns [1, 2, 3, -1, 0]
arrayUnion([1, 1, 1], [1, 1, 1]) returns [1]
public static int[] arrayUnion(int[] a, int[] b){
int[] result;
for(int i =0; i< a.length; i++){
for(int k =0; k<result.length; k++){
if(a[i]!= result[k]){
result.add(a[i]);
}
}
}
for(int j =0; j< b.length; j++){
for(int k =0; k<result.length; k++){
if(b[j]!=result[k]){
result.add(b[j]);
}
}
}
return result;
}
You can do it with a stream, merging the two arrays keeping only the distinct values single array.
int[] a = { 1, 2, 3, 2, 7, 4, 5 };
int[] b = { 2, 9, 4, 5, 5 };
int[] union = arrayUnion(a,b);
System.out.println(Arrays.toString(union));
prints
[1, 2, 3, 4, 5, 7, 9]
This works by
flattening the two arrays into an Intstream.
getting rid of duplicates
and converting back to an int array.
static int[] arrayUnion(int[] a, int[] b) {
return Stream.of(a,b).flatMapToInt(IntStream::of)
.distinct()
.toArray();
}
If you can use the Java Collections, you can use Set as follows to get the unique integers array:
public static int[] arrayUnion(int[] a, int[] b){
HashSet<Integer> set=new HashSet();
for(int i =0; i< a.length; i++){
set.add(a[i]);
}
for(int i =0; i< b.length; i++){
set.add(b[i]);
}
int n = s.size();
int[] result; = new String[n];
int j = 0;
for(Integer i: set) {
result[j++] = i;
}
return result;
}
First you can not use the add method for an array. So therefore your code could look like this:
public int[] arrayUnion(int[] a, int[] b) {
List<Integer> result = new ArrayList<>();
for (int value: a) {
if (!result.contains(value)) {
result.add(value);
}
}
for (int value: b) {
if (!result.contains(value)) {
result.add(value);
}
}
return result.stream().mapToInt(Integer::intValue).toArray();
}
Second it is a little bit easier with a set. Therefore you can easily add all values and return the array:
public int[] arrayUnion(int[] a, int[] b) {
Set<Integer> result = new HashSet<>();
for (int value: a) {
result.add(value);
}
for (int value: b) {
result.add(value);
}
return result.stream().mapToInt(Integer::intValue).toArray();
}
And there is also a third option. You can use the Java Stream API with the flatMap:
public int[] arrayUnion(int[] a, int[] b) {
return Stream.of(a, b).flatMapToInt(IntStream::of).distinct().toArray();
}
I need to add an element before every occurrence of a particular element. I can do this using for loop and calculate the index and then add the element. Is there any efficient method without using for loop or using streams.
e.g: int[] a = {1,2,4,5,7,9,2,5}
Add element {3} before every occurrence of 2 which result in {1,3,2,4,5,7,9,3,2,5}
Attempt:
int[] a = {1, 2, 4, 5, 7, 9, 2, 5};
int[] new1 = null;
int[] indexToAdd = IntStream.range(0, a.length)
.filter(i -> a[i] == 2)
.map(i -> i)
.toArray();
for(int j = 0; j<indexToAdd.length; j++){
final Integer innerj = new Integer(j);
new1 = IntStream.range(0,a.length)
.map(i -> {
if (i < indexToAdd[innerj]) {
return a[i];
} else if (i == indexToAdd[innerj]) {
return 3 ;
} else {
return a[i - 1];
}
}).toArray();
}
The most efficient way is to create another array on the fly so that we always add elements at the end which is O(1) as compared to adding elements somewhere in the middle of the array which is O(n):
int[] arr1 = {1,2,4,5,7,9,2,5};
List<Integer> list2 = new ArrayList<>();
for(int i=0; i < arr1.length; i++)
{
int elem = arr1[i];
if(elem == 2)
{
list2.add(3);
}
list2.add(elem);
}
Integer[] arr2 = list2.toArray(new Integer[0]);
arr1 = Arrays.stream(integers).mapToInt(i->i).toArray();
Another 1 liner using streams:
int[] arr1 = {1, 2, 4, 5, 7, 9, 2, 5};
arr1 = Arrays.stream(arr1)
.flatMap(x -> x == 2 ? Stream.of(3, x).mapToInt(i -> i) : Stream.of(x).mapToInt(i -> i))
.toArray();