How can I get a unique array based on object prope

2019-02-04 00:03发布

问题:

I have an array of objects and I want to get a new array from it that is unique based only on a single property, is there a simple way to achieve this?

Eg.

[ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]

Would result in 2 objects with name = bill removed once.

回答1:

Use the uniq function

var destArray = _.uniq(sourceArray, function(x){
    return x.name;
});

From the docs:

Produces a duplicate-free version of the array, using === to test object equality. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iterator function.

In the above example, the function uses the objects name in order to determine uniqueness.



回答2:

If you prefer to do things yourself without Lodash, and without getting verbose, try this uniq filter with optional uniq by property:

const uniqFilterAccordingToProp = function (prop) {
    if (prop)
        return (ele, i, arr) => arr.map(ele => ele[prop]).indexOf(ele[prop]) === i
    else
        return (ele, i, arr) => arr.indexOf(ele) === i
}

Then, use it like this:

const obj = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
obj.filter(uniqFilterAccordingToProp('abc'))

Or for plain arrays, just omit the parameter, while remembering to invoke:

[1,1,2].filter(uniqFilterAccordingToProp())



回答3:

If you want to check all the properties then lodash 4 comes with _.uniqWith(sourceArray, _.isEqual)



回答4:

A better and quick approach

var table = [
  {
    a:1,
    b:2
  },
  {
    a:2,
    b:3
  },
  {
    a:1,
    b:4
  }
];

let result = [...new Set(table.map(item => item.a))];
document.write(JSON.stringify(result));

Found here



回答5:

You can use the _.uniqBy function

var array = [ { id: 1, name: 'bob' }, { id: 2, name: 'bill' }, { id: 1, name: 'bill' },{ id: 2, name: 'bill' } ];

var filteredArray = _.uniqBy(array,function(x){ return x.id && x.name;});

console.log(filteredArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>

In the above example, filtering is based on the uniqueness of combination of properties id & name.

if you have multiple properties for an object. then to find unique array of objects based on specific properties, you could follow this method of combining properties inside _.uniqBy() method.



回答6:

In case you need pure JavaScript solution:

var uniqueProperties = {};

var notUniqueArray = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ];


for(var object in notUniqueArray){
   uniqueProperties[notUniqueArray[object]['name']] = notUniqueArray[object]['id'];
}

var uniqiueArray = [];

for(var uniqueName in uniqueProperties){
   uniqiueArray.push(
     {id:uniqueProperties[uniqueName],name:uniqueName});
}

//uniqiueArray


回答7:

I was looking for a solution which didn't require a library, and put this together, so I thought I'd add it here. It may not be ideal, or working in all situations, but it's doing what I require, so could potentially help someone else:

const uniqueBy = (items, reducer, dupeCheck = [], currentResults = []) => {
  if (!items || items.length === 0) return currentResults;
  
  const thisValue = reducer(items[0]);
  
  const resultsToPass = dupeCheck.indexOf(thisValue) === -1 ?
    [...currentResults, items[0]] : currentResults;
    
  return uniqueBy(
    items.slice(1),
    reducer,
    [...dupeCheck, thisValue],
    resultsToPass,
  );    
}

const testData = [
  {text: 'hello', image: 'yes'},
  {text: 'he'},
  {text: 'hello'},
  {text: 'hell'},
  {text: 'hello'},
  {text: 'hellop'},
];

const results = uniqueBy(
  testData,
  item => {
    return item.text
  },
)

console.dir(results)