Tenho uma série de objetos parecidos com:
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"}
...
];
Como você pode ver, alguns nomes se repetem. Quero obter uma nova matriz apenas com nomes, mas se algum nome se repetir, não quero adicioná-lo novamente. Eu quero esta matriz:
var newArray = ["Name1", "Name2"];
Estou tentando fazer isso com map
:
var newArray = array.map((a) => {
return a.name;
});
Mas o problema é que isso retorna:
newArray = ["Name1", "Name1", "Name2", "Name2"];
Como posso definir alguma condição interna map
, para que não retorne um elemento que já existe? Desejo fazer isso com map
ou algum outro recurso ECMAScript 5 ou ECMAScript 6.
javascript
arrays
snoopy 25
fonte
fonte
Set
? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Respostas:
Com o ES6, você pode usar
Set
para valores únicos, após mapear apenas os nomes dos objetos.Esta proposta usa uma sintaxe difusa
...
para coletar os itens em uma nova matriz.fonte
...
fazer?...
para construir um array com um objeto iterável.Array.from
transmite a intenção de conversão muito melhor (e também é mais fácil de entender / pesquisar por novatos), a sintaxe de propagação deve ser usada apenas onde o elemento de propagação é um entre muitos. Talvez chamar isso de "prática ruim" seja um pouco duro demais, desculpe, só espero evitar que isso se torne um idioma comum.Se você estiver procurando por uma solução JavaScript que não seja ES 6 (sem Set), você pode usar o método Array
reduce
:fonte
var names = array.reduce(function(a, b) { a.indexOf(b.name) === -1 && a.push(b.name) return a; }, []);
Pessoalmente, não vejo por que todo mundo está ficando tão extravagante com o ES 6. Se fosse meu código, preferiria oferecer suporte ao maior número de navegadores possível.
fonte
indexOf
-ing o tempo todo? Por exemplo, façaadded[name] = true
e emif(added[name])
vez deif(a.indexOf(name))
.goto fail
, vazando sua variável de índice para o escopo delimitador, etc. etc. ES6 foi codificado no padrão por boas razões e é para a maioria parte trivialmente fácil de polyfill / transform para navegadores mais antigos.Você também pode simplesmente combinar
map
comfilter
fonte
Você pode usar Object.keys () para obter a matriz dos nomes de propriedade enumeráveis de um determinado objeto a partir do resultado do objeto da
array
variável iterativa com Array.prototype.reduce () onde as chaves são os nomes destruídosCódigo:
fonte
Muitas boas respostas aqui. Eu só gostaria de contribuir com alguma diversidade na esperança de dar a vocês uma outra perspectiva.
Os arrays são do tipo de objeto em JavaScript, portanto, podem ser usados como hash ao mesmo tempo. Ao usar essa funcionalidade, podemos simplificar muito o trabalho a ser feito em uma única operação de redução com complexidade de tempo O (n).
Se você não está satisfeito com seu array contendo algumas propriedades além das chaves de array, você pode considerar manter um objeto hash separado também.
fonte
p[c.name]
coisas em um objeto separadoo
e depois descartá-lo.Concordo que, se você só precisa dos
name
valores, aSet
é o caminho a seguir.No entanto , se você deseja obter uma matriz de objetos exclusivos com base na
name
propriedade, sugiro usar umMap
. Uma maneira rápida de criar um mapa é por meio de uma matriz de[key, value]
matrizes:Um benefício adicional do
Map
é que você obtém afilter
funcionalidade que corta os não-únicos, sem perder a conexão com os objetos de origem. Claro, ele só é necessário se você precisar fazer referência ao conjunto exclusivo de objetos várias vezes.fonte
Se você está limitado a ES5, eu usaria o Lodash's
_.uniq
fonte
Com ES6, isso deve fazer o trabalho.
fonte
map
deve ser usado com funções puras, não para ter efeitos colaterais. Isso seria um trabalho paraforEach
oureduce
.Usando UnderscoreJS,
`
fonte
No ES5, use um objeto como um dicionário para desempenho O ( n ).
Isso só funcionará se todas as chaves forem Strings.
Você poderia fazer a mesma coisa em uma expressão se quiser:
mas acho a forma imperativa mais fácil de ler.
fonte
function (item) { return item.name; }
Object.keys()
, esta resposta costumafilter()
manter apenas os nomes que ainda não foram armazenados no mapa, o que é bastante elegante.Experimente isto:
fonte
Use
array#forEach()
earray#indexOf()
métodos como este se você deseja compatibilidade máxima ainda, sintaxe concisa:No entanto, se a compatibilidade não for um problema use o objeto ECMAScript 6 e métodos como este:
Set
array#map
Array.from()
fonte
Foi assim que fiz, usando um array vazio separado.
fonte
Para quem procura um 1 liner
ou sem usar métodos no protótipo do array
pode ser útil para escrever algumas funções puras para lidar com este
fonte
fonte