简体   繁体   中英

javascript and es6 filter array with unique key

I have a list in variable like:

var name_list = some_list

console.log(name_list)

Array[3]
   0: Object
       name: "Johny"
   1: Object
       name: "Monty"
   2: Object3:
      name: "Johny"

I want to get the list with non repetitive list. How can I do this ?

Update

I tried with this..

var unique_name = [ ...new Set(name_list.map(name => {
                return name.name
            }))]

It works fine but I want the object that are filtered unique according to name.

Any idea ??

reduce over the array keeping a lookup of previous entries to check against.

 const arr=[{name:"Johny"},{name:"Monty"},{name:"Johny"}]; function dedupeByKey(arr, key) { const tmp = {}; return arr.reduce((p, c) => { const k = c[key]; if (tmp[k]) return p; tmp[k] = true; return p.concat(c); }, []); } console.log(dedupeByKey(arr, 'name'));

Or you can filter using a similar approach:

 const arr=[{name:"Johny"},{name:"Monty"},{name:"Johny"}]; function dedupeByKey(arr, key) { const temp = arr.map(el => el[key]); return arr.filter((el, i) => temp.indexOf(el[key]) === i ); } console.log(dedupeByKey(arr, 'name'));

Another approach I don't see in here would be to use a Map

var name_list = [{name: "Johny"}, {name: "Monty"}, {name: "Johny"}];

// Make a mapping of name to object, then pullout objects.
var name_map = new Map(name_list.map(o => [o.name, o]));
var unique_names = [...name_map.values()];

Note, this will take the last object for each name instead of the first, but you could always do name_list.slice().reverse().map( instead of you need specifically the first object found.

Filter to keep only those elements which are the first occurrence of the name (in other words, whose index is the same as the index of the first occurrence):

 var name_list = [{name: "Johny"}, {name: "Monty"}, {name: "Johny"}]; var filtered = name_list . filter( (elt, i, a) => i === a.findIndex( elt2 => elt.name === elt2.name ) ); document.getElementById('result').textContent = JSON.stringify(filtered);
 <pre id='result'></pre>

This might not be the fastest approach, but it could be the simplest.

You can use this little distinctByProp( theArray, propertyName) function.

I hope it helps

distinctByProp = (theArray, prop) => {
    let tempArray = [];
    let isFound = obj => tempArray.find( n => n[prop] === obj[prop]);
    theArray.forEach( current => !isFound(current) && tempArray.push(current));
    return tempArray;
}

Usage is like:

let names_list = [{name: "Johny"}, {name: "Johnyh"}, {name: "Max"}, {name: "Monty"}, {name: "Johnyh"}, {name: "Max"}];

let distinct = distinctByProp(names_list, "name");

console.log(distinct);

I hope it helps

You could use Array#filter() .

 var name_list = [{ name: "Johny" }, { name: "Monty" }, { name: "Johny" }], filtered = name_list.filter(a => { this.my = this.my || Object.create(null); if (!this.my[a.name]) { this.my[a.name] = true; return true; } }); document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');

This is my resumed form of this type of unique. Not only for one field but for all the root fields of the object.

const unique = l => l.filter(
  (e1, i, a) => i === a.findIndex(
    e2 => Object.keys(e1)
      .map(x => e1[x] === e2[x])
      .reduce((x,y) => x && y)
  )
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM