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

我从服务器得到两个对象数组,如下所示:
var duplicateTestData = [
    { 
        licenseId: 'xxx',batchId: '123',reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time) 
    },{ 
        licenseId: 'yyy',batchId: '124',{ 
        licenseId: 'aaa',batchId: '145',reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time) 
    }
];

var finalResult = [
    { 
        reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time),license: {},testType: 'P1',productType: 'Flower',licenseId: 'xxx',createType: 'DataUpload' 
    },{ 
        reportDate: Fri Dec 11 2015 00:00:00 GMT+0530 (India Standard Time),licenseId: 'yyy',licenseId: 'aaa',{ 
        reportDate: Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time),licenseId: 'zzz',createType: 'DataUpload' 
    }
]

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

[
    { 
        reportDate: Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time),createType: 'DataUpload' 
    } 
]

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

for(var j=0;j < duplicateTestData.length;j++){
    for (var i = 0; i < finalResult.length; i++) {
        if (
            (finalResult[i].licenseId == duplicateTestData[j].licenseId)  && 
            (finalResult[i].reportDate == duplicateTestData[j].reportDate) &&
            (finalResult[i].batchId == duplicateTestData[j].batchId)
        ) {
            finalResult.splice(i,1);
            break;
        }
    }
}

console.log(finalResult);

解决方法

简单的出路
finalResult.filter(({batchId:a,licenseId:b,reportDate:c}) =>
  duplicateTestData.find(({batchId:x,licenseId:y,reportDate:z}) =>
    a === x && b === y && c === z) === undefined)

=> [ { reportDate: 'Fri Dec 14 2015 00:00:00 GMT+0530 (India Standard Time)',createType: 'DataUpload' } ]

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

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

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

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

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

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

// arrayCompare :: (a -> b -> Bool) -> [a] -> [b] -> Bool
const arrayCompare = f=> ([x,...xs])=> ([y,...ys])=> {
  if (x === undefined && y === undefined)
    return true
  else if (! f (x) (y))
    return false
  else
    return arrayCompare (f) (xs) (ys)
}

// keys :: Object(k:v) -> [k]
const keys = Object.keys

// objectCompare :: (v -> v -> Bool) -> Object(k:v) -> Object(k:v) -> Bool
const objectCompare = f=> a=> b=>
  arrayCompare (x=> y=> f (a[x]) (b[y]) && f (a[y]) (b[y])) (keys(a)) (keys(b))

// objectEqual :: Object -> Object -> Bool
const objectEqual = objectCompare (x=> y=> x === y)

// sample data
let xs = [
  {a:1,b:10},{a:2,b:20},{a:3,b:30}
]

let ys = [
  {a:1,b:30},{a:4,b:40}
]

// return all ys that are not present in xs
var result = ys.filter(y=> xs.find(objectEqual(y)) === undefined)

console.log(result)
// [{a:4,b:40}]

好厉害

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

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

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

// subsetObjectEquals :: Object -> Object -> Bool
const subsetObjectEquals = objectCompare (x=> y=> y === undefined || x === y)

// this time use subsetObjectEquals
var result = finalResult.filter(x=>
  duplicateTestData.find(subsetObjectEquals(x)) === undefined)

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

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

充分的工作实例

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

// arrayCompare :: (a -> b -> Bool) -> [a] -> [b] -> Bool
const arrayCompare = f=> ([x,...ys])=> {
  if (x === undefined && y === undefined)
    return true
  else if (! f (x) (y))
    return false
  else
    return arrayCompare (f) (xs) (ys)
}

// keys :: Object(k:v) -> [k]
const keys = Object.keys

// objectCompare :: (v -> v -> Bool) -> Object(k:v) -> Object(k:v) -> Bool
const objectCompare = f=> a=> b=>
  arrayCompare (x=> y=> f (a[x]) (b[x]) && f (a[y]) (b[y])) (keys(a)) (keys(b))

// objectEqual :: Object -> Object -> Bool
const objectEqual = objectCompare (x=> y=> x === y)

// subsetObjectEquals :: Object -> Object -> Bool
const subsetObjectEquals = objectCompare (x=> y=> y === undefined || x === y)

// your data
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)' }
  ];

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' }               
]

// get all finalResult items that do not subsetObjectEqual items in duplicateTestData
var result = finalResult.filter(x=>
  duplicateTestData.find(subsetObjectEquals(x)) === undefined)

console.log(result)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


kindeditor4.x代码高亮功能默认使用的是prettify插件,prettify是Google提供的一款源代码语法高亮着色器,它提供一种简单的形式来着色HTML页面上的程序代码,实现方式如下: 首先在编辑器里面插入javascript代码: 确定后会在编辑器插入这样的代码: <pre
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代码高亮,因为SyntaxHighlighter的应用非常广泛,所以将kindeditor默认的prettify替换为SyntaxHighlighter代码高亮插件 上一篇“让kindeditor显示高亮代码”中已经
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小
JS怎么获取当前时间戳
JS如何判断对象是否为数组
JS怎么获取图片当前宽高
JS对象如何转为json格式字符串
JS怎么获取图片原始宽高
怎么在click事件中调用多个js函数
js如何往数组中添加新元素
js如何拆分字符串
JS怎么对数组内元素进行求和
JS如何判断屏幕大小
js怎么解析json数据
js如何实时获取浏览器窗口大小
原生JS实现别踩白块小游戏(五)
原生JS实现别踩白块小游戏(一)