2

Basically I want to group the object which has same value of key.

const dupObj = [
  {
    "uuid": "",
    "quantity": 0,
    "distributeStoreUuid": "",
    "distributeStore__acceptanceTaskDetailsUuid": "",
    "acceptanceTaskUuid": "acabb997-fc06-47ba-ae29-d7aea9a6a022",
  },
  {
    "uuid": "",
    "quantity": 3,
    "acceptanceTaskUuid": "acabb997-fc06-47ba-ae29-d7aea9a6a022",
  }
 ]

and here is the expected result

[
 {
   "uuid": "",
   "quantity": 3,
   "distributeStoreUuid": "",
   "distributeStore__acceptanceTaskDetailsUuid": "",
   "acceptanceTaskUuid": "acabb997-fc06-47ba-ae29-d7aea9a6a022",
 }
]

I'm experimenting with ES6 Set and here what I have so far

const uniKeys = [...(new Set(dupObj.map(({ acceptanceTaskUuid }) => acceptanceTaskUuid)))];

Any idea? Thanks in advance

8
  • same value of key is which column?acceptanceTaskUuid or uuid or distributeStoreUuid or acceptanceTaskUuid? Commented Feb 8, 2018 at 6:48
  • Sorry forgot to mention key. It's acceptanceTaskUuid Commented Feb 8, 2018 at 6:49
  • 1
    What is the logic when you have the same property but different values for the same object (quantity in your example)? Commented Feb 8, 2018 at 6:50
  • it will store the latter. The earlier quantity discarded Commented Feb 8, 2018 at 6:51
  • 1
    Please provide a bit more extensive input (with maybe 4, 5 entries) and desired output for it. Commented Feb 8, 2018 at 6:53

5 Answers 5

2

The following code should work:

const dedupe = originalArray => originalArray.reduce((array, obj) => {
  const index = array.findIndex(item => item.acceptanceTaskUuid === obj.acceptanceTaskUuid)
    
  // if there already is no other acceptance task uuid
  // then append the obj to the array else add the quantities together
  return index === -1 ? [...array, obj] : Object.assign([], array, {
    [index]: Object.assign({}, array[index], obj)
  })
}, [])

console.log(dedupe([
  {
    "uuid": "",
    "quantity": 0,
    "distributeStoreUuid": "",
    "distributeStore__acceptanceTaskDetailsUuid": "",
    "acceptanceTaskUuid": "acabb997-fc06-47ba-ae29-d7aea9a6a022",
  },
  {
    "uuid": "",
    "quantity": 3,
    "acceptanceTaskUuid": "acabb997-fc06-47ba-ae29-d7aea9a6a022",
  },
  {
    "uuid": "",
    "quantity": 4,
    "acceptanceTaskUuid": "foobar"
  },
  {
    "uuid": "",
    "quantity": 13,
    "acceptanceTaskUuid": "foobarbaz",
  },
  {
    "uuid": "",
    "quantity": 6,
    "acceptanceTaskUuid": "foobar",
  },
]))

The findIndex function returns the index of the first item in the array which matches the condition. Basically the code above starts with an empty array, loops over the original array (reduce) and finds the index of the item with the same acceptance task uuid as the current object each iteration. If there is a duplicate then it adds the quantities together, else it just appends the new item to the array

EDIT: Made Immutable

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

2 Comments

would love to see it in ES6 style
Ok used arrow functions
1

You can reduce the array into a Map. On a each pass, get the object with the same acceptanceTaskUuid from the Map, or use an empty object, assign this to current. Use forEach to iterate the array's object (o) entries, and check if the property is a number in current, and add it, or assign it if not. Then spread the Map values to get an array:

const dupObj = [{"uuid":"","quantity":1,"distributeStoreUuid":"","distributeStore__acceptanceTaskDetailsUuid":"","acceptanceTaskUuid":"acabb997-fc06-47ba-ae29-d7aea9a6a022"},{"uuid":"","quantity":3,"acceptanceTaskUuid":"acabb997-fc06-47ba-ae29-d7aea9a6a022"}]

const uniques = [...dupObj.reduce((m, o) => {
  const current = m.get(o.acceptanceTaskUuid) || {}

  Object.entries(o).forEach(([key, value]) => 
    current[key] = typeof current[key] === 'number' ? current[key] + value : value)

  return m.set(o.acceptanceTaskUuid, current)
}, new Map()).values()]

console.log(uniques)

Comments

0

You can use array#reduce and store object on the acceptanceTaskUuid key, if a duplicate object appears, merge them using Object.assign. Then extract the values using Object.values().

const dupObj = [ { "uuid": "", "quantity": 0, "distributeStoreUuid": "", "distributeStore__acceptanceTaskDetailsUuid": "", "acceptanceTaskUuid": "acabb997-fc06-47ba-ae29-d7aea9a6a022", }, { "uuid": "", "quantity": 3, "acceptanceTaskUuid": "acabb997-fc06-47ba-ae29-d7aea9a6a022"} ],
      result = Object.values(dupObj.reduce((r, o) => {
        r[o.acceptanceTaskUuid] = Object.assign(r[o.acceptanceTaskUuid] || {}, o);
        return r;
      }, {}));
console.log(result);

2 Comments

and arrow function should not return assignment. That is what Eslint validate.
Updated the solution to merge the values.
0

You could use a Map (or plain JS object) with the key being your id and value the object and then use Object.assign() to merge duplicate objects together.

This is a simple loop algorithm without any fancy reduce or mapping operation, it should be simple to understand.

let map = new Map();
for (let obj of dupObj) {
    if (map.has(obj.acceptanceTaskUuid))
        map.set(obj.acceptanceTaskUuid, Object.assign(map.get(obj.acceptanceTaskUuid), obj)); // merge
    else
        map.set(obj.acceptanceTaskUuid, obj);
}

// map.values() return an iterator, not an array
for (let obj of map.values()) {
    console.log(obj);
}

1 Comment

@GuyWhoKnowsStuff It's not adding it takes the latest values as OP explained it? His comment was "it will store the latter. The earlier quantity discarded".
-2

Why not using lodash, so easy, so simple.

https://lodash.com/docs/4.17.5#filter

2 Comments

I want to avoid extra loaded library.
Well, OK, (But you didn't mentioned that.. :-) )

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.