4

I'm trying to get rid of duplicates in array of objects. I want my code linear so I'm using hashtable:

output = Array.from(new Set(output.map(e => e.company)))
  .map(company => { return output.find(e => e.company === company) })

This code works properly for this array of objects:

let output = [
  { company: 'sony'},
  { company: 'sony'},
  { company: 'apple'}
]

but thing is that I want to reuse this code so I would like to move it to function which would take array output and company string. I don't know how to do that, I tried like this:

const uniq = (array, key) => {
  return Array.from(new Set(array.map( e => e[key] )))
    .map(key => { return array.find(e => e[key] === key) })
}

but this return array of two undefined.


Also second thing is that it's pretty complicated code for such trivial task. Isn't there some easier way to do same without losing performance?

6 Answers 6

3

This one-liner works with arbitrary objects, not necessarily key:value pairs:

let uniqBy = (a, key) => [...new Map(a.map(x => [x[key], x]).reverse()).values()];

//

let data = [
    {company: 'sony', more: 1},
    {company: 'apple', more: 1},
    {company: 'sony', more: 2},
    {company: 'sony', more: 3},
    {company: 'apple', more: 3},
]

console.log(uniqBy(data, 'company'))

If you don't care about the order of the result, you can also skip .reverse().

Sign up to request clarification or add additional context in comments.

2 Comments

I think this and @Nina Scholz are my personal favourite solutions
Also it looks like it's just slightly faster but rather insignificant jsperf.com/filter-arr-of-obj-2/1
2

You could map the unique values and create a new object.

const 
    unique = (array, key) => Array.from(new Set(array.map(o => o[key])), value => ({ [key]: value }));

var output = [{ company: 'sony'}, { company: 'sony'}, { company: 'apple'}];

console.log(unique(output, "company"));

Comments

1

You have naming conflicts, just rename the second key:

let input = [{ company: "sony" }, { company: "sony" }, { company: "apple" }];

const uniq = (array, key) => {
  return Array.from(new Set(array.map(e => e[key]))).map(key1 => {
    //                                                   ^^^^
    return array.find(e => e[key] === key1);
    //                                ^^^^
  });
};

const result = uniq(input, "company");

console.log(result);

Comments

1

I think the issue is you are overwriting the definition of key in the .map() callback. This version - with a separate variable name for the callback parameter - seems to do what you need:

let output = [
  { company: 'sony'},
  { company: 'sony'},
  { company: 'apple'}
]
const uniq = (array, key) => {
  return Array.from(new Set(array.map( e => e[key] )))
    .map(x => { return array.find(e => e[key] === x) })
}

console.log(uniq(output, "company"));

Comments

1

You need to rename your second map parameter to something other than key, otherwise the key inside find will not be the parameter key that is passed to the function:

let output = [
  { company: 'sony'},
  { company: 'sony'},
  { company: 'apple'}
]

const uniq = (array, key) => {
  return Array.from(new Set(array.map( e => e[key] )))
    .map(k => { return array.find(e => e[key] === k) })
}

console.log(uniq(output, 'company'));

Comments

0

If you are allowed to use Lodash there is a simple way of eliminating duplicates

_.uniqBy(your_data, 'company');

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.