比较两个数组的内容
Compare content of two array
我需要比较两个对象数组 (source/target) 的内容。
如果源中的项目在目标中不存在,我应该只添加项目以包含。
如果源中的项目确实存在于目标中,我应该只添加项目以排除。
目前正在使用 ramda R.differenceWith()
,但当目标为空时出现问题。
我想知道 differenceWith
这里是否适合海豚,或者我可以使用其他功能。请提供示例谢谢!
注意:即使不使用 ramda 也可以回答。
// source
const pathHash1 = {
hash: "c4ca4238a0b923820dcc509a6f75849b",
path: "./source/file1.txt"
};
const pathHash2 = {
hash: "c81e728d9d4c2f636f067f89cc14862c",
path: "./source/file2.txt"
};
const pathHash3 = {
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./souce/file3.txt"
};
// target
const pathHash4 = {
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./target/file3.txt"
};
// works
// const source = [pathHash1, pathHash2, pathHash3]
// const target = [pathHash4]
// does no work
const source = [pathHash1, pathHash2, pathHash3]
const target = []
// result pathHash1, pathHash2
const resultInclude = R.differenceWith((x,y)=> x.hash === y.hash, source, target)
const resultExclude= R.differenceWith((x,y)=> x.hash !== y.hash, source, target)
console.log('include',resultInclude.map(x=>x.hash))
console.log('exclude',resultExclude.map(x=>x.hash))
我认为您可以对简单对象使用 difference
而不是 differenceWith
。如果你想在 source
和 target
中找到共同的对象,我建议使用 innerJoin
:
const {difference, innerJoin, equals} = R;
const a = [{x: 1}, {y: 2}, {z: 3}];
const b = [{a: 0}, {x: 1}];
console.log(
difference(a, b)
);
console.log(
innerJoin(equals, a, b)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
在 vanilla js 中你可以考虑使用这个版本:
const resultInclude = pathHashListSource.filter(x => !pathHashListTarget.find(y => y.hash === x.hash));
const resultExclude = pathHashListSource.filter(x => pathHashListTarget.find(y => y.hash === x.hash));
你从R.differenceWith()得到的结果是正确的,因为这种方法的来源是:
var differenceWith = _curry3(function differenceWith(pred, first, second) {
var out = [];
var idx = 0;
var firstLen = first.length;
while (idx < firstLen) {
if (!_includesWith(pred, first[idx], second) &&
!_includesWith(pred, first[idx], out)) {
out.push(first[idx]);
}
idx += 1;
}
return out;
});
如您所见,差异是使用 _includesWith 计算得出的。但是,当第二个数组为空时,将填充正在进行的输出数组(无重复项)。
// source
const pathHash1 = {
hash: "c4ca4238a0b923820dcc509a6f75849b",
path: "./source/file1.txt"
};
const pathHash2 = {
hash: "c81e728d9d4c2f636f067f89cc14862c",
path: "./source/file2.txt"
};
const pathHash3 = {
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./souce/file3.txt"
};
// target
const pathHash4 = {
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./target/file3.txt"
};
// works
// const source = [pathHash1, pathHash2, pathHash3]
// const target = [pathHash4]
// issue
const source = [pathHash1, pathHash2, pathHash3]
const target = []
// result pathHash1, pathHash2
const resultInclude = R.differenceWith((x,y)=> x.hash === y.hash, source, target)
const resultExclude= R.differenceWith((x,y)=> x.hash !== y.hash, source, target)
console.log('include',resultInclude.map(x=>x.hash))
console.log('exclude',resultExclude.map(x=>x.hash))
<script src="https://cdn.jsdelivr.net/npm/ramda@latest/dist/ramda.min.js"></script>
对排除情况使用 R.innerJoin
:
const getInclude = R.differenceWith(R.eqProps('hash'))
const getExclude = R.innerJoin(R.eqProps('hash'))
const pathHash1 = {hash: "c4ca4238a0b923820dcc509a6f75849b",path: "./source/file1.txt"},pathHash2 = {hash: "c81e728d9d4c2f636f067f89cc14862c",path: "./source/file2.txt"},pathHash3 = {hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",path: "./souce/file3.txt"},pathHash4 = {hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",path: "./target/file3.txt"}
const source1 = [pathHash1, pathHash2, pathHash3]
const target1 = [pathHash4]
const source2 = [pathHash1, pathHash2, pathHash3]
const target2 = []
const getHash = R.map(R.prop('hash'))
console.log('include1', getHash(getInclude(source1, target1)))
console.log('exclude1', getHash(getExclude(source1, target1)))
console.log('include2', getHash(getInclude(source2, target2)))
console.log('exclude2', getHash(getExclude(source2, target2)))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
此处的另一个选择是构建目标哈希的本机 Set
并使用 R.partition
根据哈希是否存在于 [=] 中将源列表拆分为两个列表12=].
const source = [
{
hash: "c4ca4238a0b923820dcc509a6f75849b",
path: "./source/file1.txt"
},
{
hash: "c81e728d9d4c2f636f067f89cc14862c",
path: "./source/file2.txt"
},
{
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./souce/file3.txt"
}
]
const target = [
{
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./target/file3.txt"
}
]
////
const targetHashes =
target.reduce((hashes, next) => hashes.add(next.hash), new Set)
const [resultExclude, resultInclude] =
R.partition(x => targetHashes.has(x.hash), source)
////
console.log("resultInclude", resultInclude)
console.log("resultExclude", resultExclude)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
我需要比较两个对象数组 (source/target) 的内容。
如果源中的项目在目标中不存在,我应该只添加项目以包含。
如果源中的项目确实存在于目标中,我应该只添加项目以排除。
目前正在使用 ramda R.differenceWith()
,但当目标为空时出现问题。
我想知道 differenceWith
这里是否适合海豚,或者我可以使用其他功能。请提供示例谢谢!
注意:即使不使用 ramda 也可以回答。
// source
const pathHash1 = {
hash: "c4ca4238a0b923820dcc509a6f75849b",
path: "./source/file1.txt"
};
const pathHash2 = {
hash: "c81e728d9d4c2f636f067f89cc14862c",
path: "./source/file2.txt"
};
const pathHash3 = {
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./souce/file3.txt"
};
// target
const pathHash4 = {
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./target/file3.txt"
};
// works
// const source = [pathHash1, pathHash2, pathHash3]
// const target = [pathHash4]
// does no work
const source = [pathHash1, pathHash2, pathHash3]
const target = []
// result pathHash1, pathHash2
const resultInclude = R.differenceWith((x,y)=> x.hash === y.hash, source, target)
const resultExclude= R.differenceWith((x,y)=> x.hash !== y.hash, source, target)
console.log('include',resultInclude.map(x=>x.hash))
console.log('exclude',resultExclude.map(x=>x.hash))
我认为您可以对简单对象使用 difference
而不是 differenceWith
。如果你想在 source
和 target
中找到共同的对象,我建议使用 innerJoin
:
const {difference, innerJoin, equals} = R;
const a = [{x: 1}, {y: 2}, {z: 3}];
const b = [{a: 0}, {x: 1}];
console.log(
difference(a, b)
);
console.log(
innerJoin(equals, a, b)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
在 vanilla js 中你可以考虑使用这个版本:
const resultInclude = pathHashListSource.filter(x => !pathHashListTarget.find(y => y.hash === x.hash));
const resultExclude = pathHashListSource.filter(x => pathHashListTarget.find(y => y.hash === x.hash));
你从R.differenceWith()得到的结果是正确的,因为这种方法的来源是:
var differenceWith = _curry3(function differenceWith(pred, first, second) {
var out = [];
var idx = 0;
var firstLen = first.length;
while (idx < firstLen) {
if (!_includesWith(pred, first[idx], second) &&
!_includesWith(pred, first[idx], out)) {
out.push(first[idx]);
}
idx += 1;
}
return out;
});
如您所见,差异是使用 _includesWith 计算得出的。但是,当第二个数组为空时,将填充正在进行的输出数组(无重复项)。
// source
const pathHash1 = {
hash: "c4ca4238a0b923820dcc509a6f75849b",
path: "./source/file1.txt"
};
const pathHash2 = {
hash: "c81e728d9d4c2f636f067f89cc14862c",
path: "./source/file2.txt"
};
const pathHash3 = {
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./souce/file3.txt"
};
// target
const pathHash4 = {
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./target/file3.txt"
};
// works
// const source = [pathHash1, pathHash2, pathHash3]
// const target = [pathHash4]
// issue
const source = [pathHash1, pathHash2, pathHash3]
const target = []
// result pathHash1, pathHash2
const resultInclude = R.differenceWith((x,y)=> x.hash === y.hash, source, target)
const resultExclude= R.differenceWith((x,y)=> x.hash !== y.hash, source, target)
console.log('include',resultInclude.map(x=>x.hash))
console.log('exclude',resultExclude.map(x=>x.hash))
<script src="https://cdn.jsdelivr.net/npm/ramda@latest/dist/ramda.min.js"></script>
对排除情况使用 R.innerJoin
:
const getInclude = R.differenceWith(R.eqProps('hash'))
const getExclude = R.innerJoin(R.eqProps('hash'))
const pathHash1 = {hash: "c4ca4238a0b923820dcc509a6f75849b",path: "./source/file1.txt"},pathHash2 = {hash: "c81e728d9d4c2f636f067f89cc14862c",path: "./source/file2.txt"},pathHash3 = {hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",path: "./souce/file3.txt"},pathHash4 = {hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",path: "./target/file3.txt"}
const source1 = [pathHash1, pathHash2, pathHash3]
const target1 = [pathHash4]
const source2 = [pathHash1, pathHash2, pathHash3]
const target2 = []
const getHash = R.map(R.prop('hash'))
console.log('include1', getHash(getInclude(source1, target1)))
console.log('exclude1', getHash(getExclude(source1, target1)))
console.log('include2', getHash(getInclude(source2, target2)))
console.log('exclude2', getHash(getExclude(source2, target2)))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
此处的另一个选择是构建目标哈希的本机 Set
并使用 R.partition
根据哈希是否存在于 [=] 中将源列表拆分为两个列表12=].
const source = [
{
hash: "c4ca4238a0b923820dcc509a6f75849b",
path: "./source/file1.txt"
},
{
hash: "c81e728d9d4c2f636f067f89cc14862c",
path: "./source/file2.txt"
},
{
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./souce/file3.txt"
}
]
const target = [
{
hash: "eccbc87e4b5ce2fe28308fd9f2a7baf3",
path: "./target/file3.txt"
}
]
////
const targetHashes =
target.reduce((hashes, next) => hashes.add(next.hash), new Set)
const [resultExclude, resultInclude] =
R.partition(x => targetHashes.has(x.hash), source)
////
console.log("resultInclude", resultInclude)
console.log("resultExclude", resultExclude)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>