3

How can I achieve this without using any library? I have tried it with some ES6 function but it ended up duplicating some items in the array. It should return unique especially when there is no child array in the array

I have three array variables:

data1 = first data

data2 = variable to be merge with data1

data3 = result of the merged variables

        let data1 = [{
            "document_id": 12264,
            "detail_info": [{
                "id": 745,
                "lot_no": "X12345",
              },
              {
                "id": 744,
                "lot_no": "Z12345",
              }
            ]
          },
          {
            "document_id": 12226,
            "detail_info": [{
                "id": 738,
                "lot_no": "B12345",
              },
              {
                "id": 739,
                "lot_no": "C12345",
              }
            ]
          },
          {
            "document_id": 12221,
            "detail_info": []
          }
        ]

        let data2 = [{
            "document_id": 12264,
            "detail_info": [{
                "id": 744,
                "lot_no": "Z12345",
              },
              {
                "id": 743,
                "lot_no": "L12345",
              }
            ]
          },
          {
            "document_id": 12226,
            "detail_info": [{
              "id": 739,
              "lot_no": "C12345",
            }]
          },
          {
            "document_id": 12229,
            "detail_info": [{
              "id": 741,
              "lot_no": "E12345",
            }]
          },
          {
            "document_id": 10095,
            "detail_info": []
          }
        ]

//**This should be the result**
      let data3=[
      {
        "document_id": 12264,
        "detail_info": [
          {
            "id": 745,
            "lot_no": "X12345",
          },
          {
            "id": 744,
            "lot_no": "Z12345",
          },
          {
            "id": 743,
            "lot_no": "L12345",
          }
        ]
      },
      {
        "document_id": 12226,
        "detail_info": [
          {
            "id": 738,
            "lot_no": "B12345",
          },
          {
            "id": 739,
            "lot_no": "C12345",
          }
        ]
      },
      {
        "document_id": 12221,
        "detail_info": []
      },
      {
        "document_id": 12229,
        "detail_info": [
          {
            "id": 741,
            "lot_no": "E12345",
          }
        ]
      },
      {
        "document_id": 10095,
        "detail_info": []
      }
    ]

2 Answers 2

2

First concatenate data1 and data2 into a single array ([...data1, ...data2]).

Then with Array.reduce(), generate a dictionary whose keys are all possible document_id found in the array.

Inside reduce, when an entry already exists for a document_id, then you have to merge the detail_info together. Create an array of all detail_info from the existing entry and the current item and remove the duplicates using a Set that you generate from the detail_info.id, then map this Set of ids to the the corresponding detail_info entries.

Finally, convert the dictionary to an array with Object.values():

const data1 = [
  { "document_id": 12264, someData: 'hello', "detail_info": [{ "id": 745, "lot_no": "X12345" },  { "id": 744, "lot_no": "Z12345" }] },
  { "document_id": 12226, "detail_info": [{ "id": 738, "lot_no": "B12345" }, { "id": 739, "lot_no": "C12345" }] },
  { "document_id": 12221, "detail_info": [] }
];

const data2 = [
  { "document_id": 12264, "detail_info": [{ "id": 744, "lot_no": "Z12345" }, { "id": 743, "lot_no": "L12345" }] },
  { "document_id": 12226, "detail_info": [{ "id": 739, "lot_no": "C12345" }] },
  { "document_id": 12229, "detail_info": [{ "id": 741, "lot_no": "E12345" }] },
  { "document_id": 10095, "detail_info": [] }
];

const distinctById = arr => [...new Set(arr.map(({ id }) => id))]
  .map(id => arr.find(info => info.id === id))

const data3 = Object.values([...data1, ...data2].reduce((acc, x) => {
  acc[x.document_id] = acc[x.document_id] || { ...x, detail_info: [] };
  acc[x.document_id].detail_info = distinctById([...acc[x.document_id].detail_info, ...x.detail_info]);
  return acc;
}, {}));

console.log(data3);

If you want to keep your detail_info array ordered by insertion, do this:

const distinctById = arr => {
  const uniqueIds = new Set(arr.map(({ id }) => id));
  return arr.filter(({ id }) => uniqueIds.delete(id));
}

console.log(distinctById([{ id: 5 }, { id: 4 }, { id: 5 }, { id: 3 }, { id: 4 }]))

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

5 Comments

It's working. Thank you so much, how can I add more for the final result if I have other than element beside document_id ?
Happy that it helps! I will update the answer to handle this case as well
Thank you so much for your help, it's totally working. I would like to ask if this way is faster/better for doing DOM manipulation, because I am using it in React.js' state, I am updating the state on it.
Since React uses a Virtual DOM, it will only update the parts of the DOM that changed, so the performance impact of changing all the state should not be a problem, since each rendering loop will actually rerender the whole page, but only patch the DOM where there are differences.
I tried your latest answer, and it's working. But do you have any idea how can I sort this? Like the last item/s added should be in the last index of the array.
0

If you just want to combine two arrays, use concat:

let data3 = data1.concat(data2);

1 Comment

When I do concat, duplication is still there.

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.