我有一个对象数组,如下所示:
var array = [
{id:123, value:"value1", name:"Name1"},
{id:124, value:"value2", name:"Name1"},
{id:125, value:"value3", name:"Name2"},
{id:126, value:"value4", name:"Name2"}
...
];
如您所见,某些名称会重复出现。我想获得一个只有名字的新数组,但是如果某些名称重复,我不想再添加它。我想要这个数组:
var newArray = ["Name1", "Name2"];
我正在尝试使用map
执行此操作:
var newArray = array.map((a) => {
return a.name;
});
但问题是这会返回:
newArray = ["Name1", "Name1", "Name2", "Name2"];
如何在map
内设置一些条件,因此它不会返回已存在的元素?我想用map
或其他一些ECMAScript 5或ECMAScript 6功能来做到这一点。
答案 0 :(得分:178)
使用ES6,在仅映射对象的名称后,可以使用Set
作为唯一值。
此提案使用spread syntax ...
收集新数组中的项目。
const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }],
names = [...new Set(array.map(a => a.name))];
console.log(names);

答案 1 :(得分:58)
如果您正在寻找非ES 6(无设置)的JavaScript解决方案,您可以使用Array's reduce
method:
var array=[
{id:123, value:"value1", name:"Name1"},
{id:124, value:"value2", name:"Name1"},
{id:125, value:"value3", name:"Name2"},
{id:126, value:"value4", name:"Name2"}
];
var names = array.reduce(function (a, b) {
if (a.indexOf(b.name) == -1) {
a.push(b.name)
}
return a;
}, []);
console.log(names);
答案 2 :(得分:16)
就我个人而言,我不明白为什么每个人都对ES 6感兴趣。如果是我的代码,我宁愿支持尽可能多的浏览器。
var array=[
{id:123, value:"value1", name:"Name1"},
{id:124, value:"value2", name:"Name1"},
{id:125, value:"value3", name:"Name2"},
{id:126, value:"value4", name:"Name2"}
];
// Create array of unique names
var a = (function(a){
for (var i = array.length; i--;)
if (a.indexOf(array[i].name) < 0) a.push(array[i].name);
return a;
})([]);
console.log(a);
答案 3 :(得分:12)
您也可以简单地将map
与filter
var array = [
{id:123, value:"value1", name:"Name1"},
{id:124, value:"value2", name:"Name1"},
{id:125, value:"value3", name:"Name2"},
{id:126, value:"value4", name:"Name2"}
];
var unique = array
.map( item => item.name )
.filter( ( item, idx, arr ) => arr.indexOf( item ) == idx )
console.log(unique)
答案 4 :(得分:9)
您可以Array.prototype.map()使用参数name
,elem
和{{1}来获取包含index
属性而不是Array.prototype.filter()的数组的数组在函数谓词中,消除重复的元素:
array
&#13;
答案 5 :(得分:6)
我同意,如果您只需要chcp
值,则name
即可。
然而,如果您想根据Set
属性获取一系列唯一对象,我建议您使用Map
。创建Map的快速方法是通过name
数组的数组:
[key, value]
&#13;
const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }],
unique = new Map(array.map(obj => [obj.name, obj]));
// To get the unique objects
const uniques = Array.from(unique.values());
// Get the names like you already did:
console.log("Names:", uniques.map(obj => obj.name));
// If you ever need the complete array of unique objects, you got a ref:
console.log(JSON.stringify(uniques));
&#13;
.as-console-wrapper { min-height: 100%; }
的另一个好处是,您可以获得切断非唯一身份的Map
功能,而不会丢失与源对象的连接。当然,只有在需要多次引用唯一的对象集时才需要它。
答案 6 :(得分:6)
这里有很多好的答案。我只想提供一些多样性,希望能给你另一种观点。
数组在JavaScript中是对象类型,因此它们可以同时用作哈希。通过使用此功能,我们可以极大地简化在O(n)时间复杂度的单个reduce操作中完成的工作。
如果您对包含数组键以外的某些属性的数组不满意,可以考虑保留一个单独的哈希对象。
right-click
答案 7 :(得分:3)
如果您仅限于ES5,我会使用Lodash's _.uniq
var newArray = _.uniq(array.map(function(a) {
return a.name;
}));
答案 8 :(得分:2)
使用ES6,这应该可以胜任。
var array=[
{id:123, value:"value1", name:"Name1"},
{id:124, value:"value2", name:"Name1"},
{id:125, value:"value3", name:"Name2"},
{id:126, value:"value4", name:"Name2"}
];
var set = new Set();
array.forEach((a)=>{
set.add(a.name);
});
console.log(Array.from(set));
&#13;
答案 9 :(得分:1)
使用UnderscoreJS,
array = [{id:123, value:"value1", name:"Name1"}, {id:124, value:"value2", name:"Name1"}, {id:125, value:"value3", name:"Name2"}, {id:126, value:"value4", name:"Name2"}];
get_names = _.pluck(_.uniq(array, 'name'), 'name')
console.log(get_names)
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
&#13;
`
答案 10 :(得分:0)
试试这个:
nArr = [];
array.forEach((a) => {
if (nArr.indexOf(a.name) < 0) {
nArr.push(a.name);
}
});
答案 11 :(得分:0)
我是怎么做到的,使用一个单独的空数组。
var array = [
{id:123, value:"value1", name:"Name1"},
{id:124, value:"value2", name:"Name1"},
{id:125, value:"value3", name:"Name2"},
{id:126, value:"value4", name:"Name2"}
];
var array2 = []
for (i=0; i<array.length;i++){
if (array2.indexOf(array[i].name) == -1){
array2.push(array[i].name);
}
}
console.log(array2)
&#13;
答案 12 :(得分:0)
在ES5中,使用对象作为O( n )性能的字典。
仅当所有键都是字符串时才会起作用。
var array = [
{id: 123, value: "value1", name: "Name1"},
{id: 124, value: "value2", name: "Name1"},
{id: 125, value: "value3", name: "Name2"},
{id: 126, value: "value4", name: "Name2"}
];
var allNames = array.map(item => item.name);
var map = {};
allNames.forEach(name => {
map[name] = true;
});
var uniqueNames = Object.keys(map);
console.log(uniqueNames);
如果您愿意,可以在一个表达式中执行相同的操作:
var uniqueNames = Object.keys(allNames.reduce((m, n) => (m[n] = true, m), {}));
但我发现命令式表格更容易阅读。
答案 13 :(得分:0)
如果要最大兼容性,请使用像这样的array#forEach()
和array#indexOf()
方法,简洁的语法:
const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }]
// initialize an empty array named names
let names = [];
// iterate through every element of `array` & check if it's 'name' key's value already in names array if not ADD it
array.forEach(function(element) { if (names.indexOf(element.name) === -1) names.push(element.name) });
// or use tilde like this:
//array.forEach(function(element) { if (~names.indexOf(element.name)) names.push(element.name) });
console.log(names);
但是,如果兼容性不是问题 ,请使用 ECMAScript 6 的Set
对象,array#map
和Array.from()
方法
const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }];
// iterate through every element from array using map and store it in Set(a Set won't have duplicates) then convert the Set back to Array(using Array.from)
let names = Array.from(new Set(array.map(element => element.name)));
console.log(names);
答案 14 :(得分:0)
我看到有很多类似扩展集的解决方案,但都不是最优的。
这个解决方案更简单、更高效,而且不需要重新创建数组:
const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }]
const res = array.map(e => e.name)
.filter((e, i, a) => a.indexOf(e) == i)
console.log(res)
答案 15 :(得分:-1)
对于那些寻求1班轮的人
const names = array.reduce((acc, {name}) => acc.includes(name) ? acc : [name, ...acc], []);
或不使用阵列原型上的方法
const { reduce, includes } = Array;
const names = reduce(array, (acc, {name}) => includes(acc, name) ? acc : [name, ...acc], []);
可以用于编写一些纯函数来处理这个
const get_uniq_values = (key, arr) => reduce(arr, (a, o) => includes(a, o[key]) ? a : [o[key], ...a], []);
答案 16 :(得分:-1)
var __array=[{id:123, value:"value1", name:"Name1"},{id:124, value:"value2", name:"Name1"},{id:125, value:"value3", name:"Name2"},{id:126, value:"value4", name:"Name2"}];
function __checkArray(__obj){
var flag = true;
for(let i=0; i < __array.length; i++){
if(__obj.id == __array.id){
flag = false;
break;
}
}
return flag;
}
var __valToPush = {id: 127, value: "value5", name: "Name3"};
if(__checkArray(__valToPush)){
__array.push(__valToPush)
}