Если элемент уже существует в массиве, не добавляйте его снова
у меня есть массив объектов, который выглядит так:
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.
16 ответов:
С 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);
Если вы ищете решение JavaScript, которое не является ES 6( Без набора), вы можете использовать массива
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);
лично я не понимаю, почему все получают все фантазии с 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);
вы также можете просто объединить
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)
можно сделать массив.прототип.map () чтобы получить массив с объектами
name
собственность и массив.прототип.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);
Я согласен, что если вам нужен только
name
значения, aSet
- это путь., если вы хотите получить массив уникальных объектов на основании
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%; }
дополнительное преимущество
Map
это то, что вы получаете обаfilter
функциональность, которая вырезает не uniques, без потери связи с исходными объектами. Конечно, это необходимо только в том случае, если вам нужно ссылаться на уникальный набор объектов несколько раз.
много хороших ответов здесь. Я просто хотел бы внести свой вклад с некоторым разнообразием с надеждой дать вам другую перспективу.
массивы имеют тип объекта в 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);
Если вы ограничены ES5, я бы использовал Лодашь это
_.uniq
var newArray = _.uniq(array.map(function(a) { return a.name; }));
С 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));
вот как я это сделал, используя отдельный пустой массив.
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)
Используя 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>
'
в 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), {}));
но я нахожу императивную форму легче читать.
попробуйте это:
nArr = []; array.forEach((a) => { if (nArr.indexOf(a.name) < 0) { nArr.push(a.name); } });
использовать
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 ' s
Set
для тех, кто ищет 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], []);
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) }