5

I have an array as follows:

const arr = [
            {company: 'a', date: '1'},
            {company: 'b', date: '1'},
            {company: 'c', date: '1'},
            {company: 'a', date: '2'},
            {company: 'a', date: '1'},
            {company: 'b', date: '2'},
          ]

I just want to know how to get the unique objects inside it. I tried using lodash with this command:

uniqBy(arr, 'date');

But it only returns:

[
  {company: "a", date: "1"},
  {company: "a", date: "2"}
]

I want something like this one:

[
  {company: "a", date: "1"},
  {company: "a", date: "2"},
  {company: "b", date: "1"},
  {company: "b", date: "2"},
  {company: "c", date: "1"},
]

Is there a way in lodash or vanilla JS to have this done?

2
  • group by or .count may help you Commented Jan 27, 2020 at 16:19
  • Your result is not unique by any normal definition, it looks like you've simply reordered the original array Commented Jan 27, 2020 at 16:20

4 Answers 4

7

With help of reduce() in pure js you I created a function which takes an array of objects and array of keys as inputs and return the array which is unique by all those keys.

Following are the steps of the algorithm:

  • First we need to create an object using reduce().
  • The key of that object will be the values of required keys which are provided each joined by -(I mentioned keyString for each object in the comment of code).
  • The object which will have same keyString means same values for given array of keys will automatically occur only once because object can't have duplicate keys
  • At last we use Object.values() to to create an array.

const arr = [
            {company: 'a', date: '1'}, //keyString = "a-1"
            {company: 'b', date: '1'}, //keyString = "b-1"
            {company: 'c', date: '1'}, //keyString = "c-1"
            {company: 'a', date: '2'}, //keyString = "a-2"
            {company: 'a', date: '1'}, //keyString = "a-1"
            {company: 'b', date: '2'}, //keyString = "b-2"
            //The item at index 0 and index 4 have same keyString so only a single of them will remain in object.
          ] 

const uniqueBy = (arr, keys) => {
  const obj = arr.reduce((ac, a) => {
    let keyString = keys.map(k => a[k]).join('-');
    ac[keyString] = a;
    return ac;
  }, {});
  return Object.values(obj);
}

console.log(uniqueBy(arr, ['company', 'date']))

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

3 Comments

Can you explain how this works? I love the implementation!
this one wokrs Thanks
@EvanBechtol Added a kind of a explanation. If you need more ask me
5

This lodash function combination should do it:

_.uniqWith(arr, _.isEqual);

If you want to consider only a combination of properties for uniqueness and leave other properties out of it, you use uniqBy() with a custom function of your own that sets the criterion. For example:

const arr = [
            {company: 'a', date: '1', clients: 3},
            {company: 'b', date: '1', clients: 2},
            {company: 'c', date: '1', clients: 2},
            {company: 'a', date: '1', clients: 1}
          ]

const uniqArr = _.uniqBy(arr, function(obj){
  return obj.company + obj.date;
});

// => [
       {company: 'a', date: '1', clients: 3},
       {company: 'b', date: '1', clients: 2},
       {company: 'c', date: '1', clients: 2}
      ]

In this example, the client property does not affect uniqueness, so the last object will be excluded because the company and date properties are the same as the first object.

3 Comments

woah this solved my prob with lodash, thanks a lot. never thought about uniqWith
It is absolutely worth to check out all lodash functions, mainly for array, object and collection, just to have a general idea of the library's capabilities.
Yeah! Just another questtion, what if I wan to limit it by only 'company' and 'date', I mean if other obects with the same 'company' and 'date' will have another attribute and I want to consider it unique.
2

Group them using company and date fields and use reduce

const arr = [{
    company: 'a',
    date: '1'
  },
  {
    company: 'b',
    date: '1'
  },
  {
    company: 'c',
    date: '1'
  },
  {
    company: 'a',
    date: '2'
  },
  {
    company: 'a',
    date: '1'
  },
  {
    company: 'b',
    date: '2'
  },
];

const res = Object.values(arr.reduce((acc, curr) => {
  const key = ['company', 'date'].map(x => curr[x]).join('-');

  if (!acc[key]) {
    acc[key] = curr;
  }

  return acc;
}, {}));

console.log(res);

Comments

1

Here with using reduce method in one line.

const arr = [
  { company: "a", date: "1" },
  { company: "b", date: "1" },
  { company: "c", date: "1" },
  { company: "a", date: "2" },
  { company: "a", date: "1" },
  { company: "b", date: "2" }
];

const updated = Object.values(
  arr.reduce(
    (acc, curr) => ({
      ...acc,
      [`${curr.company}-${curr.date}`]: { ...curr }
    }),
    {}
  )
);

console.log(updated);

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.