JavaScript:删除共享相同 属性 值的对象的重复项
JavaScript: Remove duplicates of objects sharing same property value
我有一组对象,我想根据特定的 key:value
对 trim 向下移动。我想创建一个数组,其中每个特定的 key:value
对只包含一个对象。将副本中的哪个对象复制到新数组并不一定重要。
比如我想trim基于arrayWithDuplicates
的price
属性,创建一个只包含每个值之一的新数组:
var arrayWithDuplicates = [
{"color":"red",
"size": "small",
"custom": {
"inStock": true,
"price": 10
}
},
{"color":"green",
"size": "small",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"blue",
"size": "medium",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"red",
"size": "large",
"custom": {
"inStock": true,
"price": 20
}
}
];
会变成:
var trimmedArray = [
{"color":"red",
"size": "small",
"custom": {
"inStock": true,
"price": 10
}
},
{"color":"green",
"size": "small",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"red",
"size": "large",
"custom": {
"inStock": true,
"price": 20
}
}
];
是否有 JavaScript 或 Angular 函数可以循环执行此操作?
EDIT: The property to filter on is nested within another property.
我认为 Angular 中没有内置函数,但创建一个并不难:
function removeDuplicates(originalArray, objKey) {
var trimmedArray = [];
var values = [];
var value;
for(var i = 0; i < originalArray.length; i++) {
value = originalArray[i][objKey];
if(values.indexOf(value) === -1) {
trimmedArray.push(originalArray[i]);
values.push(value);
}
}
return trimmedArray;
}
用法:
removeDuplicates(arrayWithDuplicates, 'size');
Returns:
[
{
"color": "red",
"size": "small"
},
{
"color": "blue",
"size": "medium"
},
{
"color": "red",
"size": "large"
}
]
和
removeDuplicates(arrayWithDuplicates, 'color');
Returns:
[
{
"color": "red",
"size": "small"
},
{
"color": "green",
"size": "small"
},
{
"color": "blue",
"size": "medium"
}
]
此函数通过返回一个新值来删除数组中的重复值。
function removeDuplicatesBy(keyFn, array) {
var mySet = new Set();
return array.filter(function(x) {
var key = keyFn(x), isNew = !mySet.has(key);
if (isNew) mySet.add(key);
return isNew;
});
}
var values = [{color: "red"}, {color: "blue"}, {color: "red", number: 2}];
var withoutDuplicates = removeDuplicatesBy(x => x.color, values);
console.log(withoutDuplicates); // [{"color": "red"}, {"color": "blue"}]
所以你可以像这样使用它
var arr = removeDuplicatesBy(x => x.custom.price, yourArrayWithDuplicates);
使用 Array.filter()
,通过使用 Object
作为散列来跟踪值,并过滤掉其值已包含在散列中的任何项目。
function trim(arr, key) {
var values = {};
return arr.filter(function(item){
var val = item[key];
var exists = values[val];
values[val] = true;
return !exists;
});
}
在我处理对象数组时,没有一个函数可以为您执行此操作,而且也没有将重复项作为重复项删除的规则。
在您的示例中,您删除了带有 size: small
的那个,但是如果您要使用循环来实现它,您很可能会在遍历数组时包含第一个并排除最后一个。
可能非常值得看看 lodash 之类的库并创建一个函数,该函数结合使用它的 API 方法来获得所需的行为。
这是一个可能的解决方案,您可以使用基本数组和过滤器表达式来检查新项目在附加到 return 结果之前是否会被视为重复项。
var arrayWithDuplicates = [
{"color":"red", "size": "small"},
{"color":"green", "size": "small"},
{"color":"blue", "size": "medium"},
{"color":"red", "size": "large"}
];
var reduce = function(arr, prop) {
var result = [],
filterVal,
filters,
filterByVal = function(n) {
if (n[prop] === filterVal) return true;
};
for (var i = 0; i < arr.length; i++) {
filterVal = arr[i][prop];
filters = result.filter(filterByVal);
if (filters.length === 0) result.push(arr[i]);
}
return result;
};
console.info(reduce(arrayWithDuplicates, 'color'));
你可以看看一些关于数组过滤的文献here
如果您需要提供关于要删除的项目的首选项,您可以定义额外的参数和逻辑,这些参数和逻辑将在添加到 return 值之前进行额外的 属性 检查。
希望对您有所帮助!
您可以为此使用 underscore:
//by size:
var uSize = _.uniqBy(arrayWithDuplicates, function(p){ return p.size; });
//by custom.price;
var uPrice = _.uniqBy(arrayWithDuplicates, function(p){ return p.custom.price; });
虽然不是最高效的解决方案,但很简单:
var unique = [];
duplicates.forEach(function(d) {
var found = false;
unique.forEach(function(u) {
if(u.key == d.key) {
found = true;
}
});
if(!found) {
unique.push(d);
}
});
使用 lodash
您可以轻松过滤掉它
第一个参数将是您的数组,第二个参数将是您重复的字段
_.uniqBy(arrayWithDuplicates, 'color')
它将return一个具有唯一值的数组
这是打字稿方式
public removeDuplicates(originalArray:any[], prop) {
let newArray = [];
let lookupObject = {};
originalArray.forEach((item, index) => {
lookupObject[originalArray[index][prop]] = originalArray[index];
});
Object.keys(lookupObject).forEach(element => {
newArray.push(lookupObject[element]);
});
return newArray;
}
和
let output = this.removeDuplicates(yourArray,'color');
for (let i = 0; i < arrayWithDuplicates.length; i++) {
for (let j = i + 1; j < arrayWithDuplicates.length; j++) {
if (arrayWithDuplicates[i].name === students[j].name) {
arrayWithDuplicates.splice(i, 1);
}
}
}
this will work perfectly...and this will delete first repeated array.
To delete last repeated array we only have to change
arrayWithDuplicates.splice(i, 1) ; into
arrayWithDuplicates.splice(j, 1);
您可以使用 lodash 删除重复对象:
import * as _ from 'lodash';
_.uniqBy(data, 'id');
此处“id
”是您的唯一标识符
这只是另一个 'feature' 基于 yvesmancera 的解决方案(在我开始修改自己的解决方案之后)还注意到我们目前只允许使用 IE 11,因此允许使用有限的 ES5。
var newArray = RemoveDuplicates(myArray,'Role', 2);
function RemoveDuplicates(array, objKey, rtnType) {
var list = [], values = [], value;
for (var i = 0; i < array.length; i++) {
value = array[i][objKey];
if(values.indexOf(value) === -1){
list.push(array[i]);
values.push(value);
}
}
if(rtnType == 1)
return list;
return values;
};
希望在根据单个对象 属性 值过滤掉对象时,即使不是所有数组,这也适用于大多数数组。
尝试以下功能:
function trim(items){
const ids = [];
return items.filter(item => ids.includes(item.id) ? false : ids.push(item.id));
}
我有一组对象,我想根据特定的 key:value
对 trim 向下移动。我想创建一个数组,其中每个特定的 key:value
对只包含一个对象。将副本中的哪个对象复制到新数组并不一定重要。
比如我想trim基于arrayWithDuplicates
的price
属性,创建一个只包含每个值之一的新数组:
var arrayWithDuplicates = [
{"color":"red",
"size": "small",
"custom": {
"inStock": true,
"price": 10
}
},
{"color":"green",
"size": "small",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"blue",
"size": "medium",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"red",
"size": "large",
"custom": {
"inStock": true,
"price": 20
}
}
];
会变成:
var trimmedArray = [
{"color":"red",
"size": "small",
"custom": {
"inStock": true,
"price": 10
}
},
{"color":"green",
"size": "small",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"red",
"size": "large",
"custom": {
"inStock": true,
"price": 20
}
}
];
是否有 JavaScript 或 Angular 函数可以循环执行此操作?
EDIT: The property to filter on is nested within another property.
我认为 Angular 中没有内置函数,但创建一个并不难:
function removeDuplicates(originalArray, objKey) {
var trimmedArray = [];
var values = [];
var value;
for(var i = 0; i < originalArray.length; i++) {
value = originalArray[i][objKey];
if(values.indexOf(value) === -1) {
trimmedArray.push(originalArray[i]);
values.push(value);
}
}
return trimmedArray;
}
用法:
removeDuplicates(arrayWithDuplicates, 'size');
Returns:
[
{
"color": "red",
"size": "small"
},
{
"color": "blue",
"size": "medium"
},
{
"color": "red",
"size": "large"
}
]
和
removeDuplicates(arrayWithDuplicates, 'color');
Returns:
[
{
"color": "red",
"size": "small"
},
{
"color": "green",
"size": "small"
},
{
"color": "blue",
"size": "medium"
}
]
此函数通过返回一个新值来删除数组中的重复值。
function removeDuplicatesBy(keyFn, array) {
var mySet = new Set();
return array.filter(function(x) {
var key = keyFn(x), isNew = !mySet.has(key);
if (isNew) mySet.add(key);
return isNew;
});
}
var values = [{color: "red"}, {color: "blue"}, {color: "red", number: 2}];
var withoutDuplicates = removeDuplicatesBy(x => x.color, values);
console.log(withoutDuplicates); // [{"color": "red"}, {"color": "blue"}]
所以你可以像这样使用它
var arr = removeDuplicatesBy(x => x.custom.price, yourArrayWithDuplicates);
使用 Array.filter()
,通过使用 Object
作为散列来跟踪值,并过滤掉其值已包含在散列中的任何项目。
function trim(arr, key) {
var values = {};
return arr.filter(function(item){
var val = item[key];
var exists = values[val];
values[val] = true;
return !exists;
});
}
在我处理对象数组时,没有一个函数可以为您执行此操作,而且也没有将重复项作为重复项删除的规则。
在您的示例中,您删除了带有 size: small
的那个,但是如果您要使用循环来实现它,您很可能会在遍历数组时包含第一个并排除最后一个。
可能非常值得看看 lodash 之类的库并创建一个函数,该函数结合使用它的 API 方法来获得所需的行为。
这是一个可能的解决方案,您可以使用基本数组和过滤器表达式来检查新项目在附加到 return 结果之前是否会被视为重复项。
var arrayWithDuplicates = [
{"color":"red", "size": "small"},
{"color":"green", "size": "small"},
{"color":"blue", "size": "medium"},
{"color":"red", "size": "large"}
];
var reduce = function(arr, prop) {
var result = [],
filterVal,
filters,
filterByVal = function(n) {
if (n[prop] === filterVal) return true;
};
for (var i = 0; i < arr.length; i++) {
filterVal = arr[i][prop];
filters = result.filter(filterByVal);
if (filters.length === 0) result.push(arr[i]);
}
return result;
};
console.info(reduce(arrayWithDuplicates, 'color'));
你可以看看一些关于数组过滤的文献here 如果您需要提供关于要删除的项目的首选项,您可以定义额外的参数和逻辑,这些参数和逻辑将在添加到 return 值之前进行额外的 属性 检查。
希望对您有所帮助!
您可以为此使用 underscore:
//by size:
var uSize = _.uniqBy(arrayWithDuplicates, function(p){ return p.size; });
//by custom.price;
var uPrice = _.uniqBy(arrayWithDuplicates, function(p){ return p.custom.price; });
虽然不是最高效的解决方案,但很简单:
var unique = [];
duplicates.forEach(function(d) {
var found = false;
unique.forEach(function(u) {
if(u.key == d.key) {
found = true;
}
});
if(!found) {
unique.push(d);
}
});
使用 lodash
您可以轻松过滤掉它
第一个参数将是您的数组,第二个参数将是您重复的字段
_.uniqBy(arrayWithDuplicates, 'color')
它将return一个具有唯一值的数组
这是打字稿方式
public removeDuplicates(originalArray:any[], prop) {
let newArray = [];
let lookupObject = {};
originalArray.forEach((item, index) => {
lookupObject[originalArray[index][prop]] = originalArray[index];
});
Object.keys(lookupObject).forEach(element => {
newArray.push(lookupObject[element]);
});
return newArray;
}
和
let output = this.removeDuplicates(yourArray,'color');
for (let i = 0; i < arrayWithDuplicates.length; i++) {
for (let j = i + 1; j < arrayWithDuplicates.length; j++) {
if (arrayWithDuplicates[i].name === students[j].name) {
arrayWithDuplicates.splice(i, 1);
}
}
}
this will work perfectly...and this will delete first repeated array.
To delete last repeated array we only have to change
arrayWithDuplicates.splice(i, 1) ; into
arrayWithDuplicates.splice(j, 1);
您可以使用 lodash 删除重复对象:
import * as _ from 'lodash';
_.uniqBy(data, 'id');
此处“id
”是您的唯一标识符
这只是另一个 'feature' 基于 yvesmancera 的解决方案(在我开始修改自己的解决方案之后)还注意到我们目前只允许使用 IE 11,因此允许使用有限的 ES5。
var newArray = RemoveDuplicates(myArray,'Role', 2);
function RemoveDuplicates(array, objKey, rtnType) {
var list = [], values = [], value;
for (var i = 0; i < array.length; i++) {
value = array[i][objKey];
if(values.indexOf(value) === -1){
list.push(array[i]);
values.push(value);
}
}
if(rtnType == 1)
return list;
return values;
};
希望在根据单个对象 属性 值过滤掉对象时,即使不是所有数组,这也适用于大多数数组。
尝试以下功能:
function trim(items){
const ids = [];
return items.filter(item => ids.includes(item.id) ? false : ids.push(item.id));
}