2016-03-29 21 views
3

我有两个对象阵列(我从服务器接收基于某些用户输入):使用Javascript - 比较有效的方式来“地图”两个阵列一起

array1 = [{id:1, name:Bob}, {id:2, name:John}, {id:3, name:Mary}]; 
array2 = [{id:2, field:true},{id:2, field:true}, {id:3, field:false}]; 

的ID的这两个阵列中的彼此对应(他们是用户ID)。在现实生活中,这些数组将会更大(数组1中最多8000个元素,数组2中16000个)。

我需要完成的事情是在前端,我目前只显示array2信息,显示给用户ID和字段。问题是前端用户不知道任何人的用户名,而是通过他们的名字知道他们。我需要一个包含如下所示对象的数组:{id:'',name:'',field:''}

我首先想到的是要建立一个新的阵列和“合并两个数组”:

var new_array = []; 

for (var i = 0; i < array2.length; i++) { 
    var name = 'Unknown'; 
    for (var j = 0; j < array1.length; j++) { 

    if (array1[j].id === array2[i].id) { 
     name = array1[j].name; 
    } 

    this.new_array.push({ 
     id: array2[i].id, 
     name: name, 
     field: array1[j].field 
    }); 
    } 
} 

所以我在第二阵列循环,并检查该ID的第一阵列的ID相匹配。如果是这样,我从第一个数组中取出名称,这就是用户名,这样我就可以得到用户名。

虽然有效,但前端速度很慢,需要几秒钟的时间才能做到这一点,并且如果有很多项目,用户体验感觉不好,还有很多等待。我正在寻找更有效的方式来做我需要做的事情。

+1

在你的例子中,array1的索引与它们的ID一致(如果off为1)。这是真的在你的实际数组? –

+0

是的,索引和id没什么共同之处。实际上,用户ID是8位数字,在array1中,它们可以以任意顺序从服务器返回。 – user2924127

+0

您发布的代码将为array2的每个值将一个新值推入'new_array',并且对于每个值,对于array1的每个值。因此,'new_array'的长度应该是'array1.length * array2.length',或者使用你的样本数字,'8000 * 16000'或者128百万个条目。这是真的如何工作,或者你真的只想通过匹配“ID”值合并? – Pointy

回答

3

贯穿一个阵列并创建一个对象ID值映射到的条目:

var array2idx = array2.reduce(function(map, value) { 
    map[value.id] = value; 
    return map; 
}, {}); 

现在,你可以找到一个简单的查找的array2值:

var new_array = []; 
for (var i = 0; i < array1.length; i++) { 
    var v2 = array2idx[array1[i].id]; 
    if (v2) { 
    new_array.push({ 
     id: v2.id, 
     name: array1[i].name, 
     field: array1[i].field 
    }); 
    } 
} 

这应该是相当快。在索引对象中查找id几乎不会花费任何时间。

+0

请注意,此示例代码假定OP真正想要的是在两个数组之间执行SQL'JOIN'操作,在“id”属性上。问题中的代码产生了交叉产品,但我怀疑这是实际需要的。 – Pointy

+1

简化,与原始O(n * m)相比,此解决方案是O(n + m)。 –

+1

感谢您的支持,它效果更好! – user2924127