如何将值从数组中的对象添加到另一个数组中的另一个对象?

时间:2019-08-30 19:08:10

标签: javascript

我正在尝试将一个数组中的对象值添加到另一个数组中的另一个对象中

第一个数组结构是:

var array1 = [
    { email: 'user1@example.com', status: 'offline' },
    { email: 'user2@example.com', status: 'online' },
    { email: 'user3@example.com', status: 'idle' }
]


var array2 = [
    { email: 'user1@example.com', status: '', activeTime: '1hr', logedIn: true, },
    { email: 'user1@example.com', status: '', activeTime: '1hr', logedIn: true, },
    { email: 'user1@example.com', status: '', activeTime: '1hr', logedIn: true, },
    { email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },
    { email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },
    { email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },
    { email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },
    { email: 'user3@example.com', status: '', activeTime: '1.5hr', logedIn: true, },
]

预期结果将是这样的:

var arrayJoined = [
    { email: 'user1@example.com', status: 'offline', activeTime: '1hr', logedIn: true, },
    { email: 'user1@example.com', status: 'offline', activeTime: '1hr', logedIn: true, },
    { email: 'user1@example.com', status: 'offline', activeTime: '1hr', logedIn: true, },
    { email: 'user2@example.com', status: 'online', activeTime: '2hr', logedIn: false, },
    { email: 'user2@example.com', status: 'online', activeTime: '2hr', logedIn: false, },
    { email: 'user2@example.com', status: 'online', activeTime: '2hr', logedIn: false, },
    { email: 'user2@example.com', status: 'online', activeTime: '2hr', logedIn: false, },
    { email: 'user3@example.com', status: 'idle', activeTime: '1.5hr', logedIn: true, },
]

4 个答案:

答案 0 :(得分:5)

您将要映射到第二个数组,并将两个对象合并在一起,其中电子邮件是相同的。因此,您可以使用Array.map和Object.assign:

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

答案 1 :(得分:1)

您可以使用Mapmap,与Map相比,array1将使find中的搜索值更快

let array1 = [{ email: 'user1@example.com', status: 'offline' },{ email: 'user2@example.com', status: 'online' },{ email: 'user3@example.com', status: 'idle' }]
let array2 = [{ email: 'user1@example.com', status: '', activeTime: '1hr', logedIn: true, },{ email: 'user1@example.com', status: '', activeTime: '1hr', logedIn: true, },{ email: 'user1@example.com', status: '', activeTime: '1hr', logedIn: true, },{ email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },{ email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },{ email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },{ email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },{ email: 'user3@example.com', 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))

答案 2 :(得分:1)

尝试使用foreachfind方法:

var array1 = [
   { email: 'user1@example.com', status: 'offline' },
   { email: 'user2@example.com', status: 'online' },
   { email: 'user3@example.com', status: 'idle' }
]


var array2 = [
   { email: 'user1@example.com', status: '', activeTime: '1hr', logedIn: true, },
   { email: 'user1@example.com', status: '', activeTime: '1hr', logedIn: true, },
   { email: 'user1@example.com', status: '', activeTime: '1hr', logedIn: true, },
   { email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },
   { email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },
   { email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },
   { email: 'user2@example.com', status: '', activeTime: '2hr', logedIn: false, },
   { email: 'user3@example.com', 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);

如果要检查状态是否有值:

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

答案 3 :(得分:0)

我在编写此书的前提是您正在学习Javascript,因此请记住,这并不是确定的“最佳方式”答案,而是说明您如何使用语言的各个方面来解决问题。您可能已经知道。

看来array1基本上是您的具有当前状态的用户数据库。因此,您需要遍历array2并从array1中的相应对象复制属性。

有多种方法可以解决此问题。最幼稚的方式是:

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)
        }
    }
}

但是,这有很多问题:

  • 遵循嵌套的for循环非常困难,而且效率也不高。
  • 您正在尝试创建一个NEW对象的NEW数组,以表示两个数组中对象的并集。这意味着您必须创建一个新的数组和一组新的对象。这确实效率低下,令人困惑。
  • 同一点,“复制对象”是一个棘手的主题。 tempObj = array2[i]位并不像您想象的那样起作用,因为它只是为现有对象分配了tempObj 引用;也就是说,对tempObj进行更改也会影响array2[i]

相反,让我们做一些优化:

  • array创建一个哈希表,以避免循环并简化查找主要用户对象的过程(或者仅使用带有电子邮件的对象作为键)。
  • 向已经在array2中的对象添加属性
var arr1hash = {};
for (var i=0; i<array1.length; i++){
    arr1hash[array[i].email] = i;
}
// {'user1@example.com': 1, 'user2@example.com: 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

这更容易阅读,效率更高。如果您坚持使用数组作为此信息的数据结构,我不知道如何做得更好。

但是,如果您可以控制这些结构的创建方式,则可以选择效率更高的方法。您可以创建一个对象来充当用户“数据库”,而不是使用对象数组,并使用一个通用的唯一标识符将用户数据与日志中的数据相关联:

var users = {
    '1': {email: 'foo@bar.com', status: 'offline'},//Note the keys are strings, not integers
    '2': {email: 'foo@bar.com', 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
}

这可能仍然不是“现实世界”的解决方案,因为我们倾向于将所有这些信息保存在数据库中,并使用JOIN操作将所有这些信息收集在一起。