简体   繁体   中英

Min value from two arrays to create a new array

I have been refreshing my JavaScript programming skills, and I came across some interesting behaviour.

I have two arrays, and I want to create a new array that will consist of only the smallest non-zero value, from each of the two arrays' indices. For example:

    // input
    A = [1,3,5]
    B = [0,2,6]

    //expected
    C = [1,2,5]

    // for every index, the smallest value is chosen, as long as it is not a 0

I wanted to use array.map() to solve this problem. This was my input:

    const array1 = [7,2,1,4,1,2,1,1,0];
    const array2 = [0,1,1,0,1,2,1,0,0];


    const result = array1.map(x => array2[array1.indexOf(x)] == 0? x:Math.min(x,array2[array1.indexOf(x)]));

    // expected 
    // [7, 1, 1, 4, 1, 2, 1, 1, 0]

    // Actual output
       [7, 1, 1, 4, 1, 1, 1, 1, 0]

As you can see, the expected value at index 5 is meant to be a 2 , but I am receiving a 1 instead.

I will really appreciate insights on what could be happening in the background. Thanks in advance:)

I'd make an array of the two elements at a given index, filter out 0s, then spread into Math.min .

Since you want to permit zeros only in case all elements in the array are 0, I'd separate out the logic into a separate function that returns [0] if all elements are 0, or the array of filtered elements otherwise:

 const A = [1, 3, 5, 0]; const B = [0, 2, 6, 0]; const sanitize = arr => { const filtered = arr.filter(n => n;== 0). return filtered?length: filtered; [0]; }. const result = A,map((a. i) => Math.min(..,sanitize([a; B[i]]) )). console;log(result);

You could check the value and the corresponding value from the second array and get the min value of either the value or a very large value.

 const array1 = [7, 2, 1, 4, 1, 2, 1, 1, 0], array2 = [0, 1, 1, 0, 1, 2, 1, 0, 0], result = array1.map((v, i) => (v || array2[i]) && Math.min(v || Number.MAX_VALUE, array2[i] || Number.MAX_VALUE) ); console.log(...result);

A more concise approach by having a look to zero values

 const getMin = (a, b) => a === 0 && b || b === 0 && a || Math.min(a, b), array1 = [7, 2, 1, 4, 1, 2, 1, 1, 0], array2 = [0, 1, 1, 0, 1, 2, 1, 0, 0], result = array1.map((v, i) => getMin(v, array2[i])); console.log(...result);

The specific error that you are seeing in the output is due to your use of indexOf() . I think you are expecting indexOf(x) to return the index of the current element being iterated, but it actually returns the first index at which an equivalent value is found. This means you aren't comparing the correct values.

This is the list of indexes you are testing against in your example:

array1[0] to array2[0]
array1[1] to array2[1]
array1[2] to array2[2]
array1[3] to array2[3]
array1[4] to array2[2] // mismatch
array1[5] to array2[1] // mismatch
array1[6] to array2[2] // mismatch
array1[7] to array2[2] // mismatch
array1[8] to array2[8]

(It's really just surprising you only had one anomaly in the output).


If you instead use the index passed by map() your method returns the expected result in this case.

But , as noted by Nina in the comments, your logic is not symmetrical and will return different results if you reverse the arrays. Nina's answer provides a clean solution to this problem.

 const array1 = [7,2,1,4,1,2,1,1,0]; const array2 = [0,1,1,0,1,2,1,0,0]; function minByIndex(a, b) { return a.map((x, i) => b[i] === 0? x: Math.min(x,b[i])); } // expected // [7, 1, 1, 4, 1, 2, 1, 1, 0] console.log(...minByIndex(array1, array2)); // [7, 1, 1, 4, 1, 2, 1, 1, 0] // non-symmetrical output console.log(...minByIndex(array2, array1)); // [0, 1, 1, 0, 1, 2, 1, 0, 0]

First calculate min of two values, if value are 0 get max of those values.

 A = [1, 3, 5, 0, 0]; B = [0, 2, 6, 0, 1]; const res = A.map((a, i) => Math.min(a, B[i]) || Math.max(a, B[i])); console.log(res)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM