如何使用javascript或lodash从对象数组中删除不匹配的对象

前端之家收集整理的这篇文章主要介绍了如何使用javascript或lodash从对象数组中删除不匹配的对象前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我从服务器得到两个对象数组,如下所示:
  1. var duplicateTestData = [
  2. {
  3. licenseId: 'xxx',batchId: '123',reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)
  4. },{
  5. licenseId: 'yyy',batchId: '124',{
  6. licenseId: 'aaa',batchId: '145',reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)
  7. }
  8. ];
  9.  
  10. var finalResult = [
  11. {
  12. reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time),license: {},testType: 'P1',productType: 'Flower',licenseId: 'xxx',createType: 'DataUpload'
  13. },{
  14. reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time),licenseId: 'yyy',licenseId: 'aaa',{
  15. reportDate: Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time),licenseId: 'zzz',createType: 'DataUpload'
  16. }
  17. ]

我试图从finalResult对象中只获取不匹配的对象,最终的结果将是这样的:

  1. [
  2. {
  3. reportDate: Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time),createType: 'DataUpload'
  4. }
  5. ]

我正在尝试这个,但没有得到正确的结果:

  1. for(var j=0;j < duplicateTestData.length;j++){
  2. for (var i = 0; i < finalResult.length; i++) {
  3. if (
  4. (finalResult[i].licenseId == duplicateTestData[j].licenseId) &&
  5. (finalResult[i].reportDate == duplicateTestData[j].reportDate) &&
  6. (finalResult[i].batchId == duplicateTestData[j].batchId)
  7. ) {
  8. finalResult.splice(i,1);
  9. break;
  10. }
  11. }
  12. }
  13.  
  14. console.log(finalResult);

解决方法

简单的出路
  1. finalResult.filter(({batchId:a,licenseId:b,reportDate:c}) =>
  2. duplicateTestData.find(({batchId:x,licenseId:y,reportDate:z}) =>
  3. a === x && b === y && c === z) === undefined)
  4.  
  5. => [ { reportDate: 'Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time)',createType: 'DataUpload' } ]

好的,它的作品,但这大多是垃圾.它并没有完全准确地描述你所做的比较.它的方式太具体了,一旦你的数据发生变化,它就会破裂.

继续阅读,我们可以学习一些乐趣.

所有(键和值)的对象相等…

我将从制定几个通用程序开始,以便更好地描述我们的问题的解决方案.

与其他方案相比,您将注意到的这个解决方案是,它不会对数据的内部构成假设.该解决方案不太在意对象中使用的实际键名称.

这意味着我们不会触摸任何batchId,licenseId或reportDate.通用过程可以解决这种情况下的所有事情,最好的部分是您可以一次又一次地使用您希望处理的任何数据.

  1. // arrayCompare :: (a -> b -> Bool) -> [a] -> [b] -> Bool
  2. const arrayCompare = f=> ([x,...xs])=> ([y,...ys])=> {
  3. if (x === undefined && y === undefined)
  4. return true
  5. else if (! f (x) (y))
  6. return false
  7. else
  8. return arrayCompare (f) (xs) (ys)
  9. }
  10.  
  11. // keys :: Object(k:v) -> [k]
  12. const keys = Object.keys
  13.  
  14. // objectCompare :: (v -> v -> Bool) -> Object(k:v) -> Object(k:v) -> Bool
  15. const objectCompare = f=> a=> b=>
  16. arrayCompare (x=> y=> f (a[x]) (b[y]) && f (a[y]) (b[y])) (keys(a)) (keys(b))
  17.  
  18. // objectEqual :: Object -> Object -> Bool
  19. const objectEqual = objectCompare (x=> y=> x === y)
  20.  
  21. // sample data
  22. let xs = [
  23. {a:1,b:10},{a:2,b:20},{a:3,b:30}
  24. ]
  25.  
  26. let ys = [
  27. {a:1,b:30},{a:4,b:40}
  28. ]
  29.  
  30. // return all ys that are not present in xs
  31. var result = ys.filter(y=> xs.find(objectEqual(y)) === undefined)
  32.  
  33. console.log(result)
  34. // [{a:4,b:40}]

好厉害

您将不得不调整此解决方案有些因为您没有比较所有对象键.在finalResult中的对象具有比duplicateTestData中的对象更多的键,因此有1:1个匹配.

简单来说,如果将x = {a:1}与y = {a:1,b:2}进行比较,则将x = {a:1}视为“匹配”,只要x中的所有键值都匹配所有键: y中的值

如果我们使用上面的objectEquals比较器,没有任何东西将被过滤掉finalResult,因为没有任何对象将匹配在duplicateTestData中找到的对象.既然这不是你想要的,那么我们来定义一个可以为你的案例工作的比较器

  1. // subsetObjectEquals :: Object -> Object -> Bool
  2. const subsetObjectEquals = objectCompare (x=> y=> y === undefined || x === y)
  3.  
  4. // this time use subsetObjectEquals
  5. var result = finalResult.filter(x=>
  6. duplicateTestData.find(subsetObjectEquals(x)) === undefined)

subsetObjectEquals的工作方式有所不同.我真的不会想到一个更好的名字,因为这是一个有点奇怪的比较.当y未定义时,表示该值的关键字不存在于“子集对象”中,因此不需要进行比较

  1. subsetObjectEquals(a,b)
  2. // returns true if all key:value pairs in `a` match all key:value pairs in `b`
  3. // otherwise returns false

充分的工作实例

我附上了一个实际使用您问题中包含的输入数据的完整代码段.在这里展开,运行它来看它的工作

  1. // arrayCompare :: (a -> b -> Bool) -> [a] -> [b] -> Bool
  2. const arrayCompare = f=> ([x,...ys])=> {
  3. if (x === undefined && y === undefined)
  4. return true
  5. else if (! f (x) (y))
  6. return false
  7. else
  8. return arrayCompare (f) (xs) (ys)
  9. }
  10.  
  11. // keys :: Object(k:v) -> [k]
  12. const keys = Object.keys
  13.  
  14. // objectCompare :: (v -> v -> Bool) -> Object(k:v) -> Object(k:v) -> Bool
  15. const objectCompare = f=> a=> b=>
  16. arrayCompare (x=> y=> f (a[x]) (b[x]) && f (a[y]) (b[y])) (keys(a)) (keys(b))
  17.  
  18. // objectEqual :: Object -> Object -> Bool
  19. const objectEqual = objectCompare (x=> y=> x === y)
  20.  
  21. // subsetObjectEquals :: Object -> Object -> Bool
  22. const subsetObjectEquals = objectCompare (x=> y=> y === undefined || x === y)
  23.  
  24. // your data
  25. var duplicateTestData = [{ licenseId: 'xxx',reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)' },{ licenseId: 'yyy',{ licenseId: 'aaa',reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)' }
  26. ];
  27.  
  28. var finalResult = [ { reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)',createType: 'DataUpload' },{ reportDate: 'Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time)',{ reportDate: 'Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time)',createType: 'DataUpload' }
  29. ]
  30.  
  31. // get all finalResult items that do not subsetObjectEqual items in duplicateTestData
  32. var result = finalResult.filter(x=>
  33. duplicateTestData.find(subsetObjectEquals(x)) === undefined)
  34.  
  35. console.log(result)

猜你在找的JavaScript相关文章