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!