Javascript 合并两个对象数组的最有效方法
我已经解决了这个问题。然而,我正在寻找一个更快的解决方案,因为我的变量有数千个对象 我有两个这样的阵列:Javascript 合并两个对象数组的最有效方法,javascript,arrays,performance,algorithm,merge,Javascript,Arrays,Performance,Algorithm,Merge,我已经解决了这个问题。然而,我正在寻找一个更快的解决方案,因为我的变量有数千个对象 我有两个这样的阵列: var full = [{a:'aa1',b:'bb1'},{a:'aa3',b:'bb2'},{a:'aa3',b:'bb3'},{a:'aa2',b:'bb3'}], some = [{a:'aa1',b:'bb1'},{a:'aa3',b:'bb3'}]; 如果对象存在于某个数据库中,我正试图在full中的名为c的新属性中标记。预期结果: [{a:'aa1',b:'bb1',c:
var full = [{a:'aa1',b:'bb1'},{a:'aa3',b:'bb2'},{a:'aa3',b:'bb3'},{a:'aa2',b:'bb3'}],
some = [{a:'aa1',b:'bb1'},{a:'aa3',b:'bb3'}];
如果对象存在于某个数据库中,我正试图在full
中的名为c
的新属性中标记。预期结果:
[{a:'aa1',b:'bb1',c:true},{a:'aa3',b:'bb2'},{a:'aa3',b:'bb3',c:true},{a:'aa2',b:'bb3'}]
一些重要提示:
- 有些元素总是少于完整元素
- 两个数组排序相等
var getIndexByAB = function(arr, a,b){
var initialIndex = getIndexByAB.initialIndex || 0,
len = arr.length;
for(initialIndex; initialIndex < len ;initialIndex++ ){
var el = arr[initialIndex];
if( el.b === b && el.a === a ){
getIndexByAB.initialIndex = initialIndex;
return initialIndex;
}
}
return -1;
}
var len = some.length;
for(var i = 0; i < len ; i++){
var el=some[i],
index = getIndexByAB(full,el.a,el.b);
if(index > -1) full[index].c = true;
}
var getIndexByAB=函数(arr,a,b){
var initialIndex=getIndexByAB.initialIndex | | 0,
len=arr.长度;
用于(initialIndex;initialIndex-1)已满[index].c=true;
}
UPDADE:使用Juan comment改进原始解决方案 由于数组都已排序,而且
some
严格小于full
,因此可以通过使用不同索引同时遍历两个数组来节省时间。实际上,您每次都要遍历full
以获取匹配元素的索引,因此您有O(N^2)运行时间,但您只需要从匹配的最后一个元素继续搜索。因为数组都已排序,而且一些严格小于full
,通过使用不同的索引同时遍历两个数组,可以节省一些时间。实际上,您每次都要遍历full
以获取匹配元素的索引,因此您有O(N^2)运行时间,但您只需要从您匹配的最后一个元素继续搜索。因为它们已排序,您只需传递一个索引即可开始搜索,这将避免O(N^2)。您已经在这样做了,但是将索引存储在全局变量中。相反,您应该将其作为参数传递给getIndexByAB
function getIndexByAB(arr, a,b , initialIndex){
// Was tracking last index by storing it in a global 'this.initialIndex'.
// 'this' points to 'window' in global functions. That's bad, it
// means this function can't be called on different arrays without
// resetting the global
// var initialIndex = this.initialIndex || 0,
initialIndex = initialIndex || 0;
var len = arr.length;
for(initialIndex; initialIndex < len ; initialIndex++ ){
var el = arr[initialIndex];
if( el.b === b && el.a === a ){
// Bad globals
// this.initialIndex = initialIndex;
return initialIndex;
}
}
return -1;
}
var len = some.length;
var lastValidIndex = 0;
for(var i = 0; i < len ; i++){
var el = some[i];
// Pass the index here, so it doesn't start from scratch
var index = getIndexByAB(full, el.a, el.b, lastValidIndex);
if(index > -1) {
full[index].c = true;
lastValidIndex = index;
}
}
函数getIndexByAB(arr、a、b、initialIndex){
//正在通过将上一个索引存储在全局“this.initialIndex”中来跟踪它。
//“this”指向全局函数中的“window”。这很糟糕,不是吗
//意味着在没有
//重置全球
//var initialIndex=this.initialIndex | | 0,
初始索引=初始索引| | 0;
var len=阵列长度;
用于(initialIndex;initialIndex-1){
完整[索引].c=true;
lastValidIndex=指数;
}
}
顺便说一下,如果您确实希望函数缓存一些值,下面介绍如何避免全局值。(在这种情况下,您不应该使用它)
var getIndexByAB=(函数(){
//这将只执行一次,并且是私有的
//到getIndexByAB(所有调用)
var lastGoodIndex=0;
返回函数(arr、a、b、重置索引){
如果(重置索引){
lastGoodIndex=0;
}
var len=阵列长度;
对于(var指数=lastGoodIndex;指数
或者,您可以通过将其缓存在getIndexByAB.initialIndex
中来实现以下功能,但它不是很优雅。避免这种情况的主要原因是,getIndexByAB.initialIndex
可以由任何其他人修改因为它们已排序,您只需传递一个索引即可开始搜索,这将避免O(n^2)。您已经在这样做了,但是将索引存储在全局变量中。相反,您应该将其作为参数传递给getIndexByAB
function getIndexByAB(arr, a,b , initialIndex){
// Was tracking last index by storing it in a global 'this.initialIndex'.
// 'this' points to 'window' in global functions. That's bad, it
// means this function can't be called on different arrays without
// resetting the global
// var initialIndex = this.initialIndex || 0,
initialIndex = initialIndex || 0;
var len = arr.length;
for(initialIndex; initialIndex < len ; initialIndex++ ){
var el = arr[initialIndex];
if( el.b === b && el.a === a ){
// Bad globals
// this.initialIndex = initialIndex;
return initialIndex;
}
}
return -1;
}
var len = some.length;
var lastValidIndex = 0;
for(var i = 0; i < len ; i++){
var el = some[i];
// Pass the index here, so it doesn't start from scratch
var index = getIndexByAB(full, el.a, el.b, lastValidIndex);
if(index > -1) {
full[index].c = true;
lastValidIndex = index;
}
}
函数getIndexByAB(arr、a、b、initialIndex){
//正在通过将上一个索引存储在全局“this.initialIndex”中来跟踪它。
//“this”指向全局函数中的“window”。这很糟糕,不是吗
//意味着在没有
//重置全球
//var initialIndex=this.initialIndex | | 0,
初始索引=初始索引| | 0;
var len=阵列长度;
用于(initialIndex;initialIndex-1){
完整[索引].c=true;
lastValidIndex=指数;
}
}
顺便说一下,如果您确实希望函数缓存一些值,下面介绍如何避免全局值。(在这种情况下,您不应该使用它)
var getIndexByAB=(函数(){
//这将只执行一次,并且是私有的
//到getIndexByAB(所有调用)
var lastGoodIndex=0;
返回函数(arr、a、b、重置索引){
如果(重置索引){
lastGoodIndex=0;
}
变量
// Create a copy of x without reference back to x
function clone(x){
return JSON.parse(JSON.stringify(x));
}
// Pass any number of arguments of any type. Returns true if they are all identical.
function areEqual(){
for(var i = 1, l = arguments.length, x = JSON.stringify(arguments[0]); i < arguments.length; ++i){
if(x !== JSON.stringify(arguments[i])){
return false;
}
}
return true;
}
// Your flagLabel being 'c'
function matchAndFlagWith(flagLabel,aFull,aSome){
var aFlagged = clone(aFull);
for(var i1 = 0, l1 = aSome.length, oSome; oSome = aSome[i1], i1 < l1; ++i1){
for(var i2 = 0, l2 = aFlagged.length, oFlagged; oFlagged = aFlagged[i2], i2 < l2; ++i2){
if(areEqual(oFlagged,oSome)){
oFlagged[flagLabel] = true;
}
}
}
return aFlagged;
}