Reputation: 976
Pretty straightforward.
I need to construct a function objOfMatches
that accepts two arrays and a callback. objOfMatches will build an object and return it. To build the object, objOfMatches
will test each element of the first array using the callback to see if the output matches the corresponding element (by index) of the second array. If there is a match, the element from the first array becomes a key in an object, and the element from the second array becomes the corresponding value.
function objOfMatches(array1, array2, callback) {
//create obj
var obj = {}
//loop thru first array
for(let i = 0; i < array1.length; i++) {
for (let j = 0; j < array2.length; j++) {
if (callback(array1[i]) === array2[j]) {
obj.array1[i] = array2[j];
}
}
}
return obj;
}
console.log(objOfMatches(['hi', 'howdy', 'bye', 'later', 'hello'], ['HI', 'Howdy', 'BYE', 'LATER', 'hello'], function(str) { return str.toUpperCase(); }));
// should log: { hi: 'HI', bye: 'BYE', later: 'LATER' }
Looks quite simple, yet I'm not fully understanding why does it throw a TypeError in the console. (TypeError: Cannot set property '0' of undefined)
Can someone explain what's going on?
Upvotes: 0
Views: 421
Reputation: 56754
Assuming both arrays are of equal lengths and the indexes of matching elements match, a very straightforward reduce gets you there:
const x = ['hi', 'howdy', 'bye', 'later', 'hello'],
y = ['HI', 'Howdy', 'BYE', 'LATER', 'hello'];
console.log(x.reduce((a,v,i)=>Object.assign(a,{[v]:y[i]}),{}))
If you need to check for the match existence and position, this is what you'd need to modify to make Array.prototype.reduce
work for you:
const x = ['hi', 'later', 'howdy', 'bye', 'hello', 'foo'],
y = ['HI', 'baz', 'Howdy', 'BYE', 'LATER', 'hello', 'bar'];
console.log(x.reduce((a,v)=> {
let i = y.indexOf(v.toUpperCase())
return i === -1 ? a : Object.assign(a, {[v]:y[i]})
},{}
))
Upvotes: 1
Reputation: 5250
Following your approach, you should use this obj[array1[j]] = array2[i]
, here the example:
function objOfMatches(array1, array2, callback) {
//create obj
var obj = {}
//loop thru first array
for(let i = 0; i < array1.length; i++) {
for (let j = 0; j < array2.length; j++) {
if (callback(array1[i]) === array2[j]) {
if(!array1[j] in obj) obj[array1[j]] = []
obj[array1[j]] = array2[i];
}
}
}
return obj;
}
console.log(objOfMatches(['hi', 'howdy', 'bye', 'later', 'hello'], ['HI', 'Howdy', 'BYE', 'LATER', 'hello'], function(str) { return str.toUpperCase(); }));
Upvotes: 0
Reputation: 92440
If you want to match corresponding elements you don't need to loop through both arrays. You can loop through one and use the index to find the corresponding object in the other.
reduce()
is nice for this because it will let you build your return object in place and it provides the index of the current loop iteration. You just run the test and assign the key/value if the test is true.
function objOfMatches(arr1, arr2, callback){
return arr1.reduce((obj, current, index) => {
if(arr2[index] === callback(current)) obj[current] = arr2[index]
return obj
}, {})
}
console.log(objOfMatches(['hi', 'howdy', 'bye', 'later', 'hello'], ['HI', 'Howdy', 'BYE', 'LATER', 'hello'], function(str) { return str.toUpperCase(); }));
Upvotes: 1