Удалить дубликаты из массива
У меня есть массив объектов, который выглядит так:
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.
Ответы
Ответ 1
С ES6 вы можете использовать Set
для уникальных значений после отображения только имен объектов.
В этом предложении для сбора элементов в новом массиве используется синтаксис распространения ...
.
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);
Ответ 2
Если вы ищете решение для JavaScript, которое не является ES 6 (no Set), вы можете использовать метод Array reduce
:
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);
Ответ 3
Лично я не понимаю, почему все все в порядке с 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);
Ответ 4
Вы также можете просто комбинировать 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)
Ответ 5
Вы можете сделать Array.prototype.map(), чтобы получить массив с объектами name
и чем Array.prototype.filter() с использованием параметров elem
, index
и 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"}],
names = array
.map(e => e.name)
.filter((e, i, a) => a.indexOf(e) === i);
console.log(names);
Ответ 6
Здесь много хороших ответов. Я просто хотел бы внести свой вклад с некоторым разнообразием, надеясь дать вам еще одну перспективу.
Массивы имеют тип объекта в JavaScript, поэтому они могут использоваться как хэш одновременно. Используя эту функциональность, мы можем значительно упростить работу, выполняемую в рамках одной операции сокращения с временной сложностью 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"}
],
result = array.reduce((p,c) => p[c.name] ? p : (p[c.name] = true, p.push(c.name), p), []);
console.log(result);
Ответ 7
Я согласен, что если вам нужны только значения name
, то Set
- это путь.
Однако, если вы хотите получить массив уникальных объектов на основе свойства name
, я бы предложил использовать Map
. Быстрый способ создания карты - через массив [key, value]
массивов:
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%; }
Ответ 8
Если вы ограничены ES5, я бы использовал Lodash _.uniq
var newArray = _.uniq(array.map(function(a) {
return a.name;
}));
Ответ 9
С 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));
Ответ 10
Используя 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>
Ответ 11
Попробуй это:
nArr = [];
array.forEach((a) => {
if (nArr.indexOf(a.name) < 0) {
nArr.push(a.name);
}
});
Ответ 12
Вот как я это сделал, используя отдельный пустой массив.
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
В 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), {}));
но я считаю, что императивную форму легче читать.
Ответ 14
Используйте методы 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 'name' key 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);
Ответ 15
Для тех, кто ищет 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
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)
}