Javascript 比较两个包含对象的数组以计算更改的内容?

Javascript 比较两个包含对象的数组以计算更改的内容?,javascript,lodash,Javascript,Lodash,使用平面JavaScript或使用lodash,我比较以下数组并返回已更改的值的最简单方法是什么(希望lodash有一个函数): 之前 [ {id: 0, name: 'Bob', age: 27}, {id: 1, name: 'Frank', age: 32}, {id: 2, name: 'Joe', age: 38} ] 之后 [ {id: 0, name: 'Bob', age: 27}, {id: 1, name: 'Frank', age: 33}, {i

使用平面JavaScript或使用lodash,我比较以下数组并返回已更改的值的最简单方法是什么(希望lodash有一个函数):

之前

[
  {id: 0, name: 'Bob', age: 27},
  {id: 1, name: 'Frank', age: 32},
  {id: 2, name: 'Joe', age: 38}
]
之后

[
  {id: 0, name: 'Bob', age: 27},
  {id: 1, name: 'Frank', age: 33},
  {id: 2, name: 'Joe', age: 38}
]
所以,从之前到之后,弗兰克现在已经33岁了,我怎么能简单地返回:

{id: 1, name: 'Frank', age: 33}
或更理想的结果:

{id: 1, age: 33}
编辑:

由于我的问题得到了各种各样的答案,我决定在服务器端和客户端对它们进行测试。以下是我使用生成包含10000条记录的json文件后得到的结果:

节点7.1.0

David Domain. (Flat JS filter & some): 3.396
Result: { id: 1, name: 'Frank', age: 33 }
Ben Aston (Flat JS nested itteration): 4.359
Result: { age: 33, id: 1 }
Gille Q. (Lodash reduce): 21.335
Result: { id: 1, age: 33 }
Stasovlas. (Lodash differenceBy): 1.442
Result: []  
Vignesh Murugan. (Lodash findWhere): 0
Result: _.findWhere is not a function
David Domain. (Flat JS filter & some): 6.695
Result: { id: 1, name: 'Frank', age: 33 }
Ben Aston (Flat JS nested itteration): 10.594
Result: { age: 33, id: 1 }
Gille Q. (Lodash reduce): 40.085
Result: { id: 1, age: 33 }
Stasovlas. (Lodash differenceBy): 6.499
Result: []
Firefox 50.0.2

David Domain. (Flat JS filter & some): 3.396
Result: { id: 1, name: 'Frank', age: 33 }
Ben Aston (Flat JS nested itteration): 4.359
Result: { age: 33, id: 1 }
Gille Q. (Lodash reduce): 21.335
Result: { id: 1, age: 33 }
Stasovlas. (Lodash differenceBy): 1.442
Result: []  
Vignesh Murugan. (Lodash findWhere): 0
Result: _.findWhere is not a function
David Domain. (Flat JS filter & some): 6.695
Result: { id: 1, name: 'Frank', age: 33 }
Ben Aston (Flat JS nested itteration): 10.594
Result: { age: 33, id: 1 }
Gille Q. (Lodash reduce): 40.085
Result: { id: 1, age: 33 }
Stasovlas. (Lodash differenceBy): 6.499
Result: []
这里要注意的有趣的事情是,当处理大量数据时,Lodash differenceBy似乎不起作用,在我放弃之前,我最多只能处理3条记录

@Vignesh一定在某一点上使用了下划线,但我不打算讨论这一点,因为情况已经发生了变化,我们现在使用Lodash

下面是我用来测试的代码,用于及时跟踪执行函数所花费的时间,然后循环1000次以获得执行函数的总时间1000次,然后除以1000以获得执行函数所花费的平均时间(毫秒):

var fs = require('fs');
var timely = require('timely');
var _ = require('lodash');

// Ben Aston
var ben_aston = function (a, b) {
  return a.reduce((p,c,i)=>{
    var diff = objDiff(c, b[i]);
    diff && p.push(diff);
    return p;
  }, [])
}
function objDiff(a, b) {
  var diff = Object.keys(a).reduce((p,c,i)=>{
    if (a[c] === b[c]) {
      return p;
    }
    p[c] = b[c];
    return p;
  }, {});
  if (!Object.keys(diff).length) {
    return;
  }
  diff.id = a.id;
  return diff;
}
var ben_astonT = timely(ben_aston);


// Gille Q.
var gille_q = function (before, after) {
  return _.reduce(before, function(result, value, key) {
    return _.isEqual(value, after[key]) ?
    result : result.concat({id: after[key].id, age: after[key].age});
  }, []);
}
var gille_qT = timely(gille_q);


// David Domain
var david_domain = function (before, after) {
  return after.filter( function( p, idx ) {
    return Object.keys(p).some( function( prop ) {
      return p[prop] !== before[idx][prop];
    })
  })
}
var david_domainT = timely(david_domain);


// Stasovlas
var stasovlas = function (before, after) {
  return _.differenceBy(after, before, 'age');
}
var stasovlasT = timely(stasovlas);


// Vignesh Murugan
var vignesh_murugan = function (before, after) {
  before.forEach((current) => {
    var after = _.findWhere(after,{id : current.id});
    if(!_.isEqual(after , current)) {
      return _.pick(after,"id","name");
    }
  });
}
var vignesh_muruganT = timely(vignesh_murugan);


// Load the data
var before = JSON.parse(fs.readFileSync('./before.json', 'utf8'));
var after = JSON.parse(fs.readFileSync('./after.json', 'utf8'));

// Open average tracking
var ben_aston_ave = 0,
    gille_q_ave = 0,
    david_domain_ave = 0,
    stasovlas_ave = 0,
    vignesh_murugan_ave = 0;

// Do test
for (i = 0; i < 1000; i++) {
  // Ben Aston
  ben_astonT(before, after);
  ben_aston_ave += ben_astonT.time;

  // Gille Q.
  gille_qT(before, after);
  gille_q_ave += gille_qT.time;

  // David Domain
  david_domainT(before, after);
  david_domain_ave += david_domainT.time;

  // Stasovlas
  stasovlasT(before, after);
  stasovlas_ave += stasovlasT.time;

  // Vignesh Murugan
  // vignesh_muruganT(before, after);
  // vignesh_murugan_ave += vignesh_muruganT.time;
}

// Calc averages
ben_aston_ave = ben_aston_ave / 1000;
gille_q_ave = gille_q_ave / 1000;
david_domain_ave = david_domain_ave / 1000;
stasovlas_ave = stasovlas_ave / 1000;
vignesh_murugan_ave = vignesh_murugan_ave / 1000;


console.log('David Domain. (Flat JS filter & some): '+david_domain_ave);
console.log('Result: { id: 1, name: \'Frank\', age: 33 }');
console.log('Ben Aston (Flat JS nested itteration): '+ben_aston_ave);
console.log('Result: { age: 33, id: 1 }');
console.log('Gille Q. (Lodash reduce): '+gille_q_ave);
console.log('Result: { id: 1, age: 33 }');
console.log('Stasovlas. (Lodash differenceBy): '+stasovlas_ave);
console.log('Result: []');
console.log('Vignesh Murugan. (Lodash findWhere): '+vignesh_murugan_ave);
console.log('Result: _.findWhere is not a function');
var fs=require('fs');
var及时=要求(“及时”);
var=要求('lodash');
//本阿斯顿
var ben_aston=函数(a,b){
返回a.reduce((p,c,i)=>{
var diff=objDiff(c,b[i]);
差异和p.push(差异);
返回p;
}, [])
}
函数objDiff(a,b){
var diff=Object.keys(a).reduce((p,c,i)=>{
如果(a[c]==b[c]){
返回p;
}
p[c]=b[c];
返回p;
}, {});
if(!Object.keys(diff.length){
返回;
}
diff.id=a.id;
返回差;
}
var ben_aston=及时(ben_aston);
//吉尔Q。
var gille_q=函数(之前、之后){
return u.reduce(在函数(结果、值、键)之前){
返回u.isEqual(值,在[key]之后)?
结果:result.concat({id:after[key].id,age:after[key].age});
}, []);
}
var gille_qT=及时(gille_q);
//大卫域
var david_domain=函数(之前、之后){
在.filter之后返回(函数(p,idx){
返回Object.keys(p).some(函数(prop){
返回p[prop]!==在[idx][prop]之前;
})
})
}
var david_domainT=及时(david_domain);
//斯塔索夫拉斯
var stasovlas=函数(之前、之后){
返回u.differenceBy(在“年龄”之后、之前);
}
var stasovlasT=及时(stasovlas);
//维涅什·穆鲁甘
var vignesh_murugan=函数(之前、之后){
before.forEach((当前)=>{
var after=..findWhere(在,{id:current.id}之后);
如果(!u.isEqual(之后,当前)){
返回选择(在“id”、“名称”之后);
}
});
}
var vignesh_murugan=及时(vignesh_murugan);
//加载数据
var before=JSON.parse(fs.readFileSync('./before.JSON','utf8');
var after=JSON.parse(fs.readFileSync('./after.JSON','utf8');
//开放平均跟踪
var ben_aston_ave=0,
gille_q_ave=0,
david_domain_ave=0,
斯塔索夫拉斯沃大街=0,
vignesh_murugan_ave=0;
//做测试
对于(i=0;i<1000;i++){
//本阿斯顿
ben_Aston(之前、之后);
本阿斯顿大街+=本阿斯顿时间;
//吉尔Q。
gille_qT(之前、之后);
gille_q_ave+=gille_qT.时间;
//大卫域
david_domainT(之前、之后);
david_domain_ave+=david_domain.time;
//斯塔索夫拉斯
stasovlasT(之前、之后);
stasovlas_ave+=stasovlasT.time;
//维涅什·穆鲁甘
//vignesh_muruganT(之前、之后);
//vignesh_murugan_ave+=vignesh_murugan.time;
}
//计算平均数
本阿斯顿大道=本阿斯顿大道/1000;
吉勒大街=吉勒大街/1000;
david_domain_ave=david_domain_ave/1000;
斯塔索瓦拉斯大道=斯塔索瓦拉斯大道/1000;
vignesh_murugan_ave=vignesh_murugan_ave/1000;
log('daviddomain.(平面JS过滤器和一些):'+David\u Domain\u ave);
log('Result:{id:1,name:\'Frank\',age:33});
console.log('Ben Aston(公寓):'+Ben_Aston_ave);
log('Result:{age:33,id:1}');
console.log('Gille Q.(洛达斯减少):'+Gille_Q_ave);
log('Result:{id:1,age:33}');
console.log('Stasovlas.(洛达斯差异):'+Stasovlas_ave);
log('Result:[]);
console.log('Vignesh Murugan.(Lodash findWhere):'+Vignesh_Murugan_ave);
log('Result:\.findWhere不是函数');
使用

您可以使用with,它将为您提供一个包含已更改项的新数组

也许是这样的:

var之前=[
{id:0,姓名:'Bob',年龄:27},
{id:1,姓名:'Frank',年龄:32},
{id:2,姓名:'Joe',年龄:38}
]
之后的var=[
{id:0,姓名:'Bobb',年龄:27},
{id:1,姓名:'Frank',年龄:33},
{id:2,姓名:'Joe',年龄:38}
]
var changed=after.filter(函数(p,idx){
返回Object.keys(p).some(函数(prop){
返回p[prop]!==在[idx][prop]之前;
})
})
console.log(已更改)
。作为控制台包装器{
最大高度:100%!重要;

}
您也可以使用lodash reduce方法进行比较,下面是我为您的示例编写的代码,其中返回了您在这个JSFIDLE中想要的内容:


假设数组索引保持不变:

功能差异(a、b){
返回a.reduce((p,c,i)=>{
var diff=objDiff(c,b[i]);
差异和p.push(差异);
返回p;
}, [])
}
函数objDiff(a,b){
var diff=Object.keys(a).reduce((p,c,i)=>{
如果(a[c]==b[c]){
返回p;
}
p[c]=b[c];
返回p;
}, {});
if(!Object.keys(diff.length){
返回;
}
diff.id=a.id;
返回差;
}
前常数=[{
id:0,姓名:'Bob',年龄:27}{
身份证号码:1,姓名:“弗兰克”,年龄:32}{
身份证号码:2,姓名:“乔”,年龄:38}]
常数后=[{
id:0,姓名:'Bob',年龄:27}{
身份证号码:1,姓名:“弗兰克”,年龄:33}{
身份证号码:2,姓名:'Joe',年龄:38}];
log(diff(before,after))I trie
  var x = [
  {id: 0, name: 'Bob', age: 27},
  {id: 1, name: 'Frank', age: 32},
  {id: 2, name: 'Joe', age: 38}
]

var y = [
  {id: 0, name: 'Bob', age: 27},
  {id: 1, name: 'Frank', age: 33},
  {id: 2, name: 'Joe', age: 38}
]

  x.forEach((current) => {
    var after = _.findWhere(y,{id : current.id})
    if(!_.isEqual(after , current)){
      console.log(_.pick(after,"id","name"))
    }
  })
var difference = [];

x.forEach((current) => {
  var after = _.find(y,{id : current.id})
  if(!_.isEqual(after , current)){
    difference.push(_.pick(after,"id","name"))
  }
})

console.log(difference)