Skip to content

Instantly share code, notes, and snippets.

@suissa
Last active June 3, 2018 04:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save suissa/0b40ec6200d6873f0471a9d09eb7f041 to your computer and use it in GitHub Desktop.
Save suissa/0b40ec6200d6873f0471a9d09eb7f041 to your computer and use it in GitHub Desktop.
Recriando a função uniq da lib _
const _ = require('underscore');
const list = [{"nome":"Rio Grande do Sul","id_estado":"23","sigla":"RS","id_cidade":"4174","nome_cidade":"Porto Alegre","guid":"28935af6-726e-48a5-518d-826c82269faa"},
{"nome":"Minas Gerais","id_estado":"11","sigla":"MG","id_cidade":"1630","nome_cidade":"Belo Horizonte","guid":"d3573f8e-a195-6281-83c7-9894c6555bee"},
{"nome":"Rio Grande do Sul","id_estado":"23","sigla":"RS","id_cidade":"4031","nome_cidade":"Gramado","guid":"c82a22b6-b13f-8190-f243-34efddcf561c"}];
const getUniq = field => fromThisList =>
_.uniq(fromThisList, obj => obj[field])
const fn = obj => obj['id_estado']
const uniq = (list, fn) =>
[... new Set(list.map(fn))]
.map(field => list.find(o => fn(o) === field))
const states = uniq(list, fn)
console.log(states);
const arrStates = _.uniq(list, fn)
console.log(arrStates);

Vou explicar de uma forma bem simples como pensei em criar essa função.

Seu uso:

_.uniq(list, obj => obj['id_estado'])

Perceba que precisamos passar o Array e uma função que pega exatamente o valor do campo desejado.

Sabendo que eu preciso dos valores sem duplicidade eu já sei que usarei a técnica do [... new Set(arr)] onde ele irá pegar um Array e criar um Set com seus valores e como sabemos num Set não podemos ter valores iguais, porém eu sei que ele não elimina Objetos duplicados.

Como sabemos que o segundo parâmetro é obj => obj['id_estado'] facilmente podemos inferir que se trata de um callback do map, no qual ele irá retornar os valores que quero usar como base de comparação.

list.map(fn)

list.map(o => o['field'])

// [1, 2, 1]

É exatamente esse retorno que iremos utilizar no Set:

 [... new Set(list.map(fn))]
// [1, 2]

Percebeu que encapsulei o new Set dentro de um Array e ainda usei o Spread Operator para que ele transformasse os valores do Set numa lista, por exemplo:

[1, 2, 1]
[... new Set([1, 2, 1])]
[... Set {1, 2}]
// internamente sem os [] ficaria
// 1,2
[1, 2]

Se você AINDA não o usa por favor, tire um tempo para estudar isso pois é deveras importante e útil!

Depois disso nós teremos um Array com os valores únicos que queremos utilizar, logo eu já penso em usar o map, pois eu quero retornar 1 Objeto, apenas, para cada um desses valores do Array.

Bom se temos os valores que desejamos agora basta apenas ir buscar o primeiro Objeto q vc encontrar no Array com aquele valor definido no campo.

Perceba que usei o verbo buscar, isso nos remete à função find a qual irá nos retornar o primeiro Objeto que encontrar que satisfaça sua condição.

Então na iteração do map eu pego o valor do campo e utilizo ele no callback do find para que eu possa comparar ele com o valor existente nos Objetos, seria mais ou menos isso:

map(field => list.find(o => o['field'] === field))

Porém perceba aqui o => o['field'] === field onde podemos trocar o['field'] por fn(o):

map(field => list.find(o => fn(o) === field))

Pois essa fn é especificamente para retornar o valor do campo passado por parâmetro.

Depois disso agora é só juntarmos nessa solução final:

const uniq = (list, fn) => 
  [... new Set(list.map(fn))]
    .map(field => list.find(o => fn(o) === field))

Caso você tenha alguma sugestão de como melhorar por favor comente aqui!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment