admin管理员组文章数量:1130182
I have an array of objects that looks like this:
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"}
...
];
As you can see, some names are repeated. I want to get a new array with names only, but if some name repeats I don't want to add it again. I want this array:
var newArray = ["Name1", "Name2"];
I'm trying to do this with map
:
var newArray = array.map((a) => {
return a.name;
});
But the problem is that this returns:
newArray = ["Name1", "Name1", "Name2", "Name2"];
How can I set some condition inside map
, so it won't return an element that already exists? I want to do this with map
or some other ECMAScript 5 or ECMAScript 6 feature.
I have an array of objects that looks like this:
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"}
...
];
As you can see, some names are repeated. I want to get a new array with names only, but if some name repeats I don't want to add it again. I want this array:
var newArray = ["Name1", "Name2"];
I'm trying to do this with map
:
var newArray = array.map((a) => {
return a.name;
});
But the problem is that this returns:
newArray = ["Name1", "Name1", "Name2", "Name2"];
How can I set some condition inside map
, so it won't return an element that already exists? I want to do this with map
or some other ECMAScript 5 or ECMAScript 6 feature.
17 Answers
Reset to default 221With ES6, you could use Set
for unique values, after mapping only the names of the objects.
This proposal uses a spread syntax ...
for collecting the items in a new array.
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);
If you are looking for a JavaScript solution that is not ES 6 (no Set) you can use the 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);
Personally I don't see why everyone is getting all fancy with ES 6. If it were my code I'd prefer to support as many browsers as possible.
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);
You could also simply combine map
with 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)
You can use Object.keys() to get the array of a given object's own enumerable property names from the object result of iterating array
variable with Array.prototype.reduce() where the keys are the destructed names
Code:
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 = Object.keys(
array.reduce((a, { name }) => (a[name] = 1, a), {})
)
console.log(names)
Many good answers here. I just would like to contribute with some diversity with hopes to give you another perspective.
Arrays are of object type in JavaScript, so they can be used as a hash at the same time. By using this functionality we can greatly simplify the job to be done in a single reduce operation with O(n) time complexity.
If you are not happy with your array holding some properties other than the array keys you might consider keeping a separate hash object as well.
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"}
],
result = array.reduce((p,c) => p[c.name] ? p : (p[c.name] = true, p.push(c.name), p), []);
console.log(result);
I agree that if you only need the name
values, a Set
is the way to go.
However, if you want to get an array of unique objects based on the name
property, I'd suggest to use a Map
. A quick way to create a Map, is via an array of [key, value]
arrays:
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));
.as-console-wrapper { min-height: 100%; }
An added benefit of Map
is that you get both the filter
functionality that cuts out the non-uniques, without loosing the connection with the source objects. Of course, it's only needed if you need to reference the unique set of objects multiple times.
If you're limited to ES5, I would use Lodash's _.uniq
var newArray = _.uniq(array.map(function(a) {
return a.name;
}));
With ES6 this should do the job.
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));
Using 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)
<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>
`
That's how I did it, using a separate empty array.
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)
In ES5, use an object as a dictionary for O(n) performance.
This will only work if all the keys are Strings.
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);
You could do the same thing in one expression if you like:
var uniqueNames = Object.keys(allNames.reduce((m, n) => (m[n] = true, m), {}));
but I find the imperative form easier to read.
Try this:
nArr = [];
array.forEach((a) => {
if (nArr.indexOf(a.name) < 0) {
nArr.push(a.name);
}
});
Use array#forEach()
and array#indexOf()
methods like this if you want maximum compatibility yet, concise 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" }]
// 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);
However, if compatibility is not an issue use ECMAScript 6's Set
object, array#map
and Array.from()
methods like this:
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);
I see there is a lot of spread-Set-like solutions, that aren't optimal.
This solution is simpler, more efficient and doesn't needs to recreate array:
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)
For those seeking a 1 liner
const names = array.reduce((acc, {name}) => acc.includes(name) ? acc : [name, ...acc], []);
or without using methods on the array's prototype
const { reduce, includes } = Array;
const names = reduce(array, (acc, {name}) => includes(acc, name) ? acc : [name, ...acc], []);
could be usefull for writing some pure functions for dealing with this
const get_uniq_values = (key, arr) => reduce(arr, (a, o) => includes(a, o[key]) ? a : [o[key], ...a], []);
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)
}
本文标签: javascriptRemove duplicates form an arrayStack Overflow
版权声明:本文标题:javascript - Remove duplicates form an array - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736756000a1951292.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
Set
? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – ppasler Commented Dec 28, 2016 at 14:51