The problem
I am iterating over a states array the looks like this
let states = [
['AL', 0],
['AK', 0],
['AZ', 0],
['AR', 0],
['CA', 0]......
]
and comparing it to states array that actually has values after the state code. I have a function that is trying to merge both array by checking the first array and seeing if the key (state) exists in the second array. If it does it should replace that array with the array found in the second array.
I've tried
Below is my attempt, it clearly does not work, I have tried shifting the array index and getting just the state code, but that throws an undefined error.
function mergeArrays(arr1, arr2) {
for(let i = 0; i < arr1.length; i ) {
let arr1state = arr1[i];
let arr2state = arr2[i];
if (arr1state === arr2state) {
console.log(arr1[i], arr2[i])
}
}
}
CodePudding user response:
I'd iterate over the actual states, the ones which have the correct values, and put them in a map.
Then iterate the states
array and just check if your desired value exists in said map.
let states = [['AL', 0],
['AK', 0],
['AZ', 0],
['AR', 0],
['CA', 0]];
let actualStates = [['AL', 1],
['AK', 2],
['AZ', 3],
['CA', 4]];
function merge(states, actualStates){
let map = {};
for(let actualState of actualStates) map[actualState[0]] = actualState[1];
for(let state of states) state[1] = map[state[0]] || state[1];
return states;
}
console.log(merge(states, actualStates));
CodePudding user response:
You are comparing two arrays against each other, not their keys, what you should compare is arr1state[0] === arr2state[0]
, otherwise you would be just checking ['AL', 0] === ['AL', 13]
, for example, as arr1state
actually holds ['AL', 0]
for i = 0
.
However, there's also the problem that you are expecting both arrays to have the same length, and be in the same order, to fix this you need to iterate the entire second array looking for that one state key, for every element in the first array. So, something like this:
function mergeArrays(arr1, arr2) {
for(let i = 0; i < arr1.length; i ) {
let arr1state = arr1[i][0];
for(let j = 0; j < arr2.length; j ) {
let arr2state = arr2[j][0];
if (arr1state === arr2state) {
console.log(`[${i}, ${j}] ${arr1[i]}, ${arr2[j]}`);
}
}
}
}
This example doesn't actually do the merging, as you didn't mention if you want to just replace it, or what should happen if only one of them has a value, however it should already answer your question of what's wrong, and allow you to fix your code.
CodePudding user response:
Iterate over the first array of states & find the corresponding array in the second array of states (you can use reduce
to do that):
const states1 = [
['AL', 0],
['AK', 0],
['AZ', 0],
['AR', 0],
['CA', 0],
]
const states2 = [
['AL', 1],
['AZ', 3],
['CA', 5],
]
const mergeStates = ({ arr1, arr2 }) => {
// iterate over the first array:
return arr1.reduce((a, [state1, val1]) => {
// find the corresponding item in the second array:
const item = arr2.find(([state2]) => state1 === state2)
// check if item exists
if (item) {
const [_, val2] = item
a = [...a, [state1, val2]]
} else {
a = [...a, [state1, val1]]
}
return a
}, [])
}
const merged = mergeStates({
arr1: states1,
arr2: states2
})
console.log(merged)
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Or a simpler solution:
const states1 = [
['AL', 0],
['AK', 0],
['AZ', 0],
['AR', 0],
['CA', 0],
]
const states2 = [
['AL', 1],
['AZ', 3],
['CA', 5],
]
const mergeStates = ({ arr1, arr2 }) => {
// creating objects from the arrays:
const baseObj = Object.fromEntries(arr1)
const newObj = Object.fromEntries(arr2)
// spreading the objects, so the latter
// overwrites the former if keys match
// then turning it back to an array
return Object.entries({
...baseObj,
...newObj,
})
}
const merged = mergeStates({
arr1: states1,
arr2: states2
})
console.log(merged)
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>