比较 2 个具有不同形状的对象数组并根据特定 属性 删除重复项
Compare 2 Arrays of objects with different shapes and remove duplicates based on specific property
我在 JavaScript 中有 2 个对象数组。两个数组在其对象中都包含一个名为 car_id 的类似 属性。
如何删除数组 1 中具有与数组 2 中的对象相似的汽车 ID 值的对象。
在下面的示例中,我应该得到 {car_id: 3, make: "Chevy", model: "Tahoe", year: 2003} 作为最终值。
var cars1 = [
{car_id: 1, make: "Honda", model: "Civic", year: 2001, driver: "John"},
{car_id: 2, make: "Ford", model: "F150", year: 2002, driver: "Max"},
{car_id: 3, make: "Chevy", model: "Tahoe", year: 2003, driver: "Jane"},
];
var cars2 = [
{car_id: 1, make: "Honda", color: "red", engine_no: "AB567"},
{car_id: 2, make: "Ford", color: "blue", engine_no: "AB568"},
{car_id: 6, make: "Toyota", color: "green", engine_no: "AB569"},
];
您可以创建一个包含来自 cars2
的所有 ID 的过滤数组,并使用它来过滤 cars1
中的项目,如下所示:
const cars1 = [
{car_id: 1, make: "Honda", model: "Civic", year: 2001, driver: "John"},
{car_id: 2, make: "Ford", model: "F150", year: 2002, driver: "Max"},
{car_id: 3, make: "Chevy", model: "Tahoe", year: 2003, driver: "Jane"},
];
const cars2 = [
{car_id: 1, make: "Honda", color: "red", engine_no: "AB567"},
{car_id: 2, make: "Ford", color: "blue", engine_no: "AB568"},
{car_id: 6, make: "Toyota", color: "green", engine_no: "AB569"},
];
const idFilter = cars2.map(item => item.car_id);
const filteredArray = cars1.filter(item => !idFilter.includes(item.car_id));
// test
console.log(filteredArray)
实际上 OP 寻找 difference of two sets。
与数组一样,可以基于 reduce
, and for the OP's special case does combine it with a nested find
已经可靠的方法来过滤掉不匹配的项目 ...
const cars1 = [
{car_id: 1, make: "Honda", model: "Civic", year: 2001, driver: "John"},
{car_id: 2, make: "Ford", model: "F150", year: 2002, driver: "Max"},
{car_id: 3, make: "Chevy", model: "Tahoe", year: 2003, driver: "Jane"},
];
const cars2 = [
{car_id: 1, make: "Honda", color: "red", engine_no: "AB567"},
{car_id: 2, make: "Ford", color: "blue", engine_no: "AB568"},
{car_id: 6, make: "Toyota", color: "green", engine_no: "AB569"},
];
function collectIncomplementedCarIdItem(collector, item/*, idx, arr*/) {
const { reference, list } = collector;
if (!reference.find(refItem =>
refItem.car_id === item.car_id)
) {
// in case one just wants to filter the car item reference.
//
list.push(item);
// // in case one wants to furtherly process/mutate
// // the filtered car item but does not want to have
// // the original car item reference effected.
// //
// // create a shallow copy, which for the given
// // car item structure is already sufficient enough.
// //
// list.push(Object.assign({}, item));
}
return collector;
}
console.log(
'cars1.reduce(collectIncomplementedCarIdItem, { reference: cars2, list: [] }).list ...',
cars1.reduce(collectIncomplementedCarIdItem, { reference: cars2, list: [] }).list
);
console.log(
'cars2.reduce(collectIncomplementedCarIdItem, { reference: cars1, list: [] }).list ...',
cars2.reduce(collectIncomplementedCarIdItem, { reference: cars1, list: [] }).list
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
开发人员通常不知道第二个 thisArg
argument which all Array
methods are capable of except of reduce
. Thus the above approach, now based on the more intuitiv filter
,可以重构为更易读的解决方案...
const cars1 = [
{car_id: 1, make: "Honda", model: "Civic", year: 2001, driver: "John"},
{car_id: 2, make: "Ford", model: "F150", year: 2002, driver: "Max"},
{car_id: 3, make: "Chevy", model: "Tahoe", year: 2003, driver: "Jane"},
];
const cars2 = [
{car_id: 1, make: "Honda", color: "red", engine_no: "AB567"},
{car_id: 2, make: "Ford", color: "blue", engine_no: "AB568"},
{car_id: 6, make: "Toyota", color: "green", engine_no: "AB569"},
];
function isIncomplementedCarIdItemOfBoundReference(item/*, idx, arr*/) {
const reference = this; // bound array / reference.
return !reference.find(refItem =>
refItem.car_id === item.car_id
)
}
console.log(
'cars1.filter(isIncomplementedCarIdItemOfBoundReference, cars2) ...',
cars1.filter(isIncomplementedCarIdItemOfBoundReference, cars2)
);
console.log(
'cars2.filter(isIncomplementedCarIdItemOfBoundReference, cars1) ...',
cars2.filter(isIncomplementedCarIdItemOfBoundReference, cars1)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
这可能不是最简洁的方法,也不是很通用,但它适用于您的示例和 returns 您想要的项目。我保留了与您示例中相同的变量名称,因此您可以继续尝试。
var uniqueCars = [];
for (let i = 0; i < cars1.length; i++) {
let isIn2ndArr = cars2.find(x => x.car_id === cars1[i].car_id)
if (!isIn2ndArr) uniqueCars.push(cars1[i])
}
我遍历第一个数组并尝试在第二个数组中找到 car_id。如果它不存在,isIn2ndArr 将具有未定义的值,这是假的。因此,我们现在可以只使用 if NOT 语句将项目推送到新数组。
注意一点,提醒一下:由于item本身就是对象,JS会在内存中保留对原始对象的引用。因此,如果您更改新数组中的 keys/properties 个对象,它也会影响原始 cars1 数组中的对象。 JS 可能会像那样奇怪 ;) 这个问题有几种变通方法,但这不是你的问题。
我在 JavaScript 中有 2 个对象数组。两个数组在其对象中都包含一个名为 car_id 的类似 属性。 如何删除数组 1 中具有与数组 2 中的对象相似的汽车 ID 值的对象。 在下面的示例中,我应该得到 {car_id: 3, make: "Chevy", model: "Tahoe", year: 2003} 作为最终值。
var cars1 = [
{car_id: 1, make: "Honda", model: "Civic", year: 2001, driver: "John"},
{car_id: 2, make: "Ford", model: "F150", year: 2002, driver: "Max"},
{car_id: 3, make: "Chevy", model: "Tahoe", year: 2003, driver: "Jane"},
];
var cars2 = [
{car_id: 1, make: "Honda", color: "red", engine_no: "AB567"},
{car_id: 2, make: "Ford", color: "blue", engine_no: "AB568"},
{car_id: 6, make: "Toyota", color: "green", engine_no: "AB569"},
];
您可以创建一个包含来自 cars2
的所有 ID 的过滤数组,并使用它来过滤 cars1
中的项目,如下所示:
const cars1 = [
{car_id: 1, make: "Honda", model: "Civic", year: 2001, driver: "John"},
{car_id: 2, make: "Ford", model: "F150", year: 2002, driver: "Max"},
{car_id: 3, make: "Chevy", model: "Tahoe", year: 2003, driver: "Jane"},
];
const cars2 = [
{car_id: 1, make: "Honda", color: "red", engine_no: "AB567"},
{car_id: 2, make: "Ford", color: "blue", engine_no: "AB568"},
{car_id: 6, make: "Toyota", color: "green", engine_no: "AB569"},
];
const idFilter = cars2.map(item => item.car_id);
const filteredArray = cars1.filter(item => !idFilter.includes(item.car_id));
// test
console.log(filteredArray)
实际上 OP 寻找 difference of two sets。
与数组一样,可以基于 reduce
, and for the OP's special case does combine it with a nested find
已经可靠的方法来过滤掉不匹配的项目 ...
const cars1 = [
{car_id: 1, make: "Honda", model: "Civic", year: 2001, driver: "John"},
{car_id: 2, make: "Ford", model: "F150", year: 2002, driver: "Max"},
{car_id: 3, make: "Chevy", model: "Tahoe", year: 2003, driver: "Jane"},
];
const cars2 = [
{car_id: 1, make: "Honda", color: "red", engine_no: "AB567"},
{car_id: 2, make: "Ford", color: "blue", engine_no: "AB568"},
{car_id: 6, make: "Toyota", color: "green", engine_no: "AB569"},
];
function collectIncomplementedCarIdItem(collector, item/*, idx, arr*/) {
const { reference, list } = collector;
if (!reference.find(refItem =>
refItem.car_id === item.car_id)
) {
// in case one just wants to filter the car item reference.
//
list.push(item);
// // in case one wants to furtherly process/mutate
// // the filtered car item but does not want to have
// // the original car item reference effected.
// //
// // create a shallow copy, which for the given
// // car item structure is already sufficient enough.
// //
// list.push(Object.assign({}, item));
}
return collector;
}
console.log(
'cars1.reduce(collectIncomplementedCarIdItem, { reference: cars2, list: [] }).list ...',
cars1.reduce(collectIncomplementedCarIdItem, { reference: cars2, list: [] }).list
);
console.log(
'cars2.reduce(collectIncomplementedCarIdItem, { reference: cars1, list: [] }).list ...',
cars2.reduce(collectIncomplementedCarIdItem, { reference: cars1, list: [] }).list
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
开发人员通常不知道第二个 thisArg
argument which all Array
methods are capable of except of reduce
. Thus the above approach, now based on the more intuitiv filter
,可以重构为更易读的解决方案...
const cars1 = [
{car_id: 1, make: "Honda", model: "Civic", year: 2001, driver: "John"},
{car_id: 2, make: "Ford", model: "F150", year: 2002, driver: "Max"},
{car_id: 3, make: "Chevy", model: "Tahoe", year: 2003, driver: "Jane"},
];
const cars2 = [
{car_id: 1, make: "Honda", color: "red", engine_no: "AB567"},
{car_id: 2, make: "Ford", color: "blue", engine_no: "AB568"},
{car_id: 6, make: "Toyota", color: "green", engine_no: "AB569"},
];
function isIncomplementedCarIdItemOfBoundReference(item/*, idx, arr*/) {
const reference = this; // bound array / reference.
return !reference.find(refItem =>
refItem.car_id === item.car_id
)
}
console.log(
'cars1.filter(isIncomplementedCarIdItemOfBoundReference, cars2) ...',
cars1.filter(isIncomplementedCarIdItemOfBoundReference, cars2)
);
console.log(
'cars2.filter(isIncomplementedCarIdItemOfBoundReference, cars1) ...',
cars2.filter(isIncomplementedCarIdItemOfBoundReference, cars1)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
这可能不是最简洁的方法,也不是很通用,但它适用于您的示例和 returns 您想要的项目。我保留了与您示例中相同的变量名称,因此您可以继续尝试。
var uniqueCars = [];
for (let i = 0; i < cars1.length; i++) {
let isIn2ndArr = cars2.find(x => x.car_id === cars1[i].car_id)
if (!isIn2ndArr) uniqueCars.push(cars1[i])
}
我遍历第一个数组并尝试在第二个数组中找到 car_id。如果它不存在,isIn2ndArr 将具有未定义的值,这是假的。因此,我们现在可以只使用 if NOT 语句将项目推送到新数组。
注意一点,提醒一下:由于item本身就是对象,JS会在内存中保留对原始对象的引用。因此,如果您更改新数组中的 keys/properties 个对象,它也会影响原始 cars1 数组中的对象。 JS 可能会像那样奇怪 ;) 这个问题有几种变通方法,但这不是你的问题。