2

So I have this object, and have to merge it with same selectionID, but also keep the topicName (and not overwrite it)

[
   {
      "selectionId":1,
      "topicName":"topic created or not validate"
   },
   {
      "selectionId":1,
      "topicName":"hghhhg test test"
   },
   {
      "selectionId":2,
      "topicName":"topic test"
   },
   {
      "selectionId":3,
      "topicName":"new topic for test topic name and description name(test check)"
   },
   {
      "selectionId":4,
      "topicName":"topic check check"
   },
   {
      "selectionId":4,
      "topicName":"topic check popup"
   },
   {
      "selectionId":5,
      "topicName":"test"
   }
]

Now I want to merge the selectioId, but also append the topicName to a new array in the same object so that I can loop it to display accordingly.

[
   {
      "selectionId":1,
      ["topicName":"topic created or not validate", "topicName":"hghhhg test test"] 
   }
   {
      "selectionId":2,
      "topicName":"topic test"
   }{
      "selectionId":3,
      "topicName":"new topic for test topic name and description name(test check)"
   }{
      "selectionId":4,
      ["topicName":"topic check check","topicName":"topic check popup"]
   }{
      "selectionId":5,
      "topicName":"test"
   }
]

I have tried this:

  var result = list.filter(function(v) {
        return this[v.selectionId]?
          !Object.assign(this[v.selectionId], v):
          (this[v.selectionId] = v);
      }, {});

Answer: (It does not take the topicName)

[
{selectionId: 1, topicName: "hghhhg test test"}
{selectionId: 2, topicName: "topic test"}
{selectionId: 3, topicName: "new topic for test topic name and description name(test check)"}
{selectionId: 4, topicName: "topic check popup"}
{selectionId: 5, topicName: "test"}
]

EDIT: Thank you guys! All the answers have worked! And giving results as expected.

4
  • Possible duplicate of stackoverflow.com/questions/14446511/… . Please have a look. Commented Aug 27, 2021 at 14:52
  • This ["topicName":"topic check check","topicName":"topic check popup"] kind of data type isn't valid, do you mean ? ` [{"topicName":"topic check check"},{"topicName":"topic check popup"}]` Commented Aug 27, 2021 at 14:52
  • 1
    I assume whent you write ["topicName":"topic check check","topicName":"topic check popup"] what you really mean is topicName: ["topic check check", "topic check popup"]; may I ask you to amend the question, please? Commented Aug 27, 2021 at 14:52
  • Use Array.map to create a brand new array for what you need. filter will keep your data IF your return stat is true. Commented Aug 27, 2021 at 14:56

3 Answers 3

1

You're example includes invalid syntax for an array.

["topicName":"topic check check","topicName":"topic check popup"]

This could be an array of objects:

[{"topicName":"topic check check"},{"topicName":"topic check popup"}]

Or more likely (how my example is based):

topicName: ["topic check check", "topic check popup"]

Because it is not a one-to-one input to output, it is a good use of Array.prototype.reduce.

list.reduce((acc, row) => {
  const existingSel = acc.find(e => e.selectionId === row.selectionId);
  
  // If we don't have an entry, make one.
  if (!existingSel) {
    // Use expansion of row to avoid mutating source objects
    return [ ...acc, { ...row}];
  }
  
  if (Array.isArray(existingSel.topicName)) {
    // if the topicName is an array, add to it.
    existingSel.topicName.push(row.topicName);
  } else {
    // Otherwise, make it an array with the two options.
    existingSel.topicName = [existingSel.topicName, row.topicName];
  }
  return acc;
}, []);
Sign up to request clarification or add additional context in comments.

Comments

0

You can use Array.reduce() to arrange the output according to selectionId. The output array contains objects each with a selectionId and topics array.

        
const input = [ { "selectionId":1, "topicName":"topic created or not validate" },{ "selectionId":1, "topicName":"hghhhg test test" },{ "selectionId":2, "topicName":"topic test" },{ "selectionId":3, "topicName":"new topic for test topic name and description name(test check)" },{ "selectionId":4, "topicName":"topic check check" },{ "selectionId":4, "topicName":"topic check popup" },{ "selectionId":5, "topicName":"test" } ]

const output = Object.values(input.reduce((acc, cur) => { 
    acc[cur.selectionId] = acc[cur.selectionId] || { selectionId: cur.selectionId, topics: []};
    acc[cur.selectionId].topics.push({ topicName: cur.topicName});
    return acc;
}, {}))

console.log('Output:', output); 

Comments

0

If I got right what you expect as output, you can do:

const input = [{
  "selectionId": 1,
  "topicName": "topic created or not validate"
}, {
  "selectionId": 1,
  "topicName": "hghhhg test test"
}, {
  "selectionId": 2,
  "topicName": "topic test"
}, {
  "selectionId": 3,
  "topicName": "new topic for test topic name and description name(test check)"
}, {
  "selectionId": 4,
  "topicName": "topic check check"
}, {
  "selectionId": 4,
  "topicName": "topic check popup"
}, {
  "selectionId": 5,
  "topicName": "test"
}];

const output = input.reduce((acc, item) => {
  const element = acc.find(elem => elem.selectionId === item.selectionId)

  if (element) {
    element.topicName = Array.isArray(element.topicName) ?
      element.topicName.push(item.topicName) :
      [element.topicName, item.topicName]
  } else {
    acc.push(item)
  }

  return acc;
}, []);

// test
console.log(output);

Anyway I would advise you against having different data types for topicName and keep it an array even if it contains just one value:

const input = [{
  "selectionId": 1,
  "topicName": "topic created or not validate"
}, {
  "selectionId": 1,
  "topicName": "hghhhg test test"
}, {
  "selectionId": 2,
  "topicName": "topic test"
}, {
  "selectionId": 3,
  "topicName": "new topic for test topic name and description name(test check)"
}, {
  "selectionId": 4,
  "topicName": "topic check check"
}, {
  "selectionId": 4,
  "topicName": "topic check popup"
}, {
  "selectionId": 5,
  "topicName": "test"
}];

const betterOutput = input.reduce((acc, item) => {
  const element = acc.find(elem => elem.selectionId === item.selectionId);

  if (element) {
    element.topicName.push(item.topicName);
  } else {
    acc.push({
      selectionId: item.selectionId,
      topicName: [item.topicName]
    })
  }

  return acc;
}, []);

// test
console.log(betterOutput);

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.