sasha romanov
sasha romanov

Reputation: 485

How to add value from object in an array into another object in another array?

I'm trying to add object value from one array into another object in another array

first array structure is:

var array1 = [
    { email: '[email protected]', status: 'offline' },
    { email: '[email protected]', status: 'online' },
    { email: '[email protected]', status: 'idle' }
]


var array2 = [
    { email: '[email protected]', status: '', activeTime: '1hr', logedIn: true, },
    { email: '[email protected]', status: '', activeTime: '1hr', logedIn: true, },
    { email: '[email protected]', status: '', activeTime: '1hr', logedIn: true, },
    { email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },
    { email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },
    { email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },
    { email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },
    { email: '[email protected]', status: '', activeTime: '1.5hr', logedIn: true, },
]

the expected result is to be something like this:

var arrayJoined = [
    { email: '[email protected]', status: 'offline', activeTime: '1hr', logedIn: true, },
    { email: '[email protected]', status: 'offline', activeTime: '1hr', logedIn: true, },
    { email: '[email protected]', status: 'offline', activeTime: '1hr', logedIn: true, },
    { email: '[email protected]', status: 'online', activeTime: '2hr', logedIn: false, },
    { email: '[email protected]', status: 'online', activeTime: '2hr', logedIn: false, },
    { email: '[email protected]', status: 'online', activeTime: '2hr', logedIn: false, },
    { email: '[email protected]', status: 'online', activeTime: '2hr', logedIn: false, },
    { email: '[email protected]', status: 'idle', activeTime: '1.5hr', logedIn: true, },
]

Upvotes: 1

Views: 77

Answers (4)

Charlie Patton
Charlie Patton

Reputation: 445

I'm writing this with the assumption that you're learning Javascript, so keep in mind it's not meant to be a definitive 'best way' answer, but rather to illustrate how you can approach the problem using aspects of the language you likely already know.

It looks like array1 is basically your user database with current status. So you need to iterate through array2 and copy the properties from the corresponding object in array1.

There are a number of ways to approach this problem. The most naive way would be:

var arrayJoined = [];
for (var i=0; i<array2.length; i++){
    for(var n=0; n<array1.length; n++){
        if (array1[n].email == array2[i].email){
            tempObj = array2[i]; //See warning below
            tempObj.status = array1[n].status;
            arrayJoined.push(tempObj.status)
        }
    }
}

However, there are a number of problems with this:

  • It's very difficult to follow the nested for loops, and it's not very efficient.
  • You're trying to create a NEW array of NEW objects that represents the union of the objects in the two arrays. This means you have to create a new array AND a new set of objects. This is really inefficient and confusing.
  • To that same point, "copying an object" is a tricky subject. The tempObj = array2[i] bit doesn't work as you might think, because it just assigns tempObj areference to the existing object; that is, making changes to tempObj will affect array2[i] as well.

Instead, let's do some optimizations:

  • Create a hash table from array to avoid loops and simplify looking up the primary user object (or just use an Object with emails as keys to begin with).
  • Add properties to the objects already in array2
var arr1hash = {};
for (var i=0; i<array1.length; i++){
    arr1hash[array[i].email] = i;
}
// {'[email protected]': 1, '[email protected]: 2, etc.}

for (var n=0; n<array2.length; n++){
    var email = array2[n];
    var index = arr1hash[email];//remember that arr1hash has the 'email' as a key and index in array1 as the value
    array2[i].status = array1[index].status;
}
//Now the objects in array2 will have a completed 'status' key, populated from the first object

This is a lot easier to read an a bit more efficient. If you're stuck with the arrays as the data structure for this information, I don't know how to do much better.

However, if you have control over how these structures are created, you could choose something much more efficient. Instead of an array of objects, you could create an object to serve as a user 'database' and use a common, unique identifier to correlate the user data with data in the log:

var users = {
    '1': {email: '[email protected]', status: 'offline'},//Note the keys are strings, not integers
    '2': {email: '[email protected]', status: 'offline'}
}

var log = [{id: 1, loggedIn: False, ActiveTime: '1hr'}]

//Then you can just do:

for (var i=0; i<log.length; i++){
    log[i].status=users[log[i].id].status
}

This is probably still not a 'real-world' solution, as we would tend to keep all of this information in a database and use a JOIN operation to pull all of this information together.

Upvotes: 0

StepUp
StepUp

Reputation: 38134

Try to use foreach and find method:

var array1 = [
   { email: '[email protected]', status: 'offline' },
   { email: '[email protected]', status: 'online' },
   { email: '[email protected]', status: 'idle' }
]


var array2 = [
   { email: '[email protected]', status: '', activeTime: '1hr', logedIn: true, },
   { email: '[email protected]', status: '', activeTime: '1hr', logedIn: true, },
   { email: '[email protected]', status: '', activeTime: '1hr', logedIn: true, },
   { email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },
   { email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },
   { email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },
   { email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },
   { email: '[email protected]', status: '', activeTime: '1.5hr', logedIn: true, },
];

// short version if status always has value:
array2.forEach(f=>{
    f.status = array1.find(a1 => a1.email == f.email).status;
});

console.log(array2);

If you want to check whether the status has value:

array2.forEach(f=>{
    const emailStatus = array1.find(a1 => a1.email == f.email);
    if (emailStatus && emailStatus.status)
        f.status = emailStatus.status;
});

Upvotes: 1

Code Maniac
Code Maniac

Reputation: 37755

You can use Map and map, Map will makes searching values from array1 faster as compared to find

let array1 = [{ email: '[email protected]', status: 'offline' },{ email: '[email protected]', status: 'online' },{ email: '[email protected]', status: 'idle' }]
let array2 = [{ email: '[email protected]', status: '', activeTime: '1hr', logedIn: true, },{ email: '[email protected]', status: '', activeTime: '1hr', logedIn: true, },{ email: '[email protected]', status: '', activeTime: '1hr', logedIn: true, },{ email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },{ email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },{ email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },{ email: '[email protected]', status: '', activeTime: '2hr', logedIn: false, },{ email: '[email protected]', status: '', activeTime: '1.5hr', logedIn: true, }]

let maped = new Map([ array1.map(v => [v.email,v]) ])

function merge (array1, array2) {
  return array2.map(obj => {
    var matchingObj = maped.get(obj.email)
    return Object.assign({}, obj, matchingObj)
  })
}

console.log(merge(array1,array2))

Upvotes: 1

Nathan Gingrich
Nathan Gingrich

Reputation: 171

You'll want to map over the second array and merge the two objects together, where the emails are the same. Therefore you can use Array.map and Object.assign:

function merge(array1, array2) {
  return array2.map(obj => {
    var matchingObj = array1.find(el => el.email === obj.email)
    return Object.assign({}, obj, matchingObj)
  })
}

Upvotes: 5

Related Questions