0
const input = [{
  "type": "group1@action1",
  "label": "labelA",
  "placeholders": ["b", "a", "r"]
}, {
  "type": "group1@action2",
  "label": "labelB",
  "placeholders": ["x", "y", "z"]
}, {
  "type": "group2@action123",
  "label": "labelC",
  "placeholders": ["a", "b", "c"]
}];

And I want

[
  {
    "group": "group1",
    "items": [
      {
        "action": "action1"        
        "label": "labelA",
        "placeholders": ["b", "a", "r"]
      },
      {
        "action": "action1"        
        "label": "labelB",
        "placeholders": ["x", "y", "z"]
      }
    ]
  },
  {
    "group": "group2",
    "items": [
      {
        "action": "action123"        
        "label": "labelC",
        "placeholders": ["a", "b", "c"]
      }
    ]
  }
]

My javascript code for split:

var key = "group1@action1";
console.log(key.substring(0,key.indexOf('@')));
console.log(key.substring(key.indexOf('@')-1, key.length));

I try use a Map() but the result is not my target. I need help by a javascript developer (Is not my job at 100%).

output = new Map;
input.forEach(element => {
    group = element.type.substring(0,element.type.indexOf('@'));
    action = element.type.substring(element.type.indexOf('@')-1, element.type.length)
    if (!output.has(group)) {
        output.set(group, [element]);
    } else {
        output.get(group).push(element);
    }
});

console.log(output);

actualy result is

Map(2) {
  'group1' => [
    { type: 'group1@action1', label: 'labelA', placeholders: [Array] },
    { type: 'group1@action2', label: 'labelB', placeholders: [Array] }
  ],
  'group2' => [
    {
      type: 'group2@action123',
      label: 'labelC',
      placeholders: [Array]
    }
  ]
}

I try use console.log(Object.fromEntries(output));

but the result is:

{
  group1: [{
  label: "labelA",
  placeholders: ["b", "a", "r"],
  type: "group1@action1"
}, {
  label: "labelB",
  placeholders: ["x", "y", "z"],
  type: "group1@action2"
}],
  group2: [{
  label: "labelC",
  placeholders: ["a", "b", "c"],
  type: "group2@action123"
}]
}

DEMO : https://jsfiddle.net/4xLcr9z2/

Stéphane GRILLON
  • 11,140
  • 10
  • 85
  • 154
  • i've found a way of doing this directly into an object, but the question is closed lmao – newalvaro9 Jun 20 '23 at 09:47
  • @newalvaro9 can you paste in a https://jsfiddle.net/ please? – Stéphane GRILLON Jun 20 '23 at 09:50
  • You can simply create a new object and build on it incrementally. Here is an [example](https://jsfiddle.net/Lt42x9bm/), using [reduce](https://jsfiddle.net/Lt42x9bm/) to simplify the loop syntax and using [destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) to simplify the split. – Ricky Mo Jun 20 '23 at 09:56
  • 1
    @stéphane-grillon https://pastebin.com/DhruSXcd – newalvaro9 Jun 20 '23 at 09:57

3 Answers3

2

After some tests I ended up with this code here. We use the reduce function to iterate over each item in the input array and accumulate the result in the output array, each result is split to separate group from action. Then we just search in results if we have already have a group with the new iteration group.

const input = [
  {
    "type": "group1@action1",
    "label": "labelA",
    "placeholders": ["b", "a", "r"]
  },
  {
    "type": "group1@action2",
    "label": "labelB",
    "placeholders": ["x", "y", "z"]
  },
  {
    "type": "group2@action123",
    "label": "labelC",
    "placeholders": ["a", "b", "c"]
  }
];

const output = input.reduce((result, item) => {
  const [group, action] = item.type.split("@");
  const existingGroup = result.find(groupItem => groupItem.group === group);

  if (existingGroup) {
    existingGroup.items.push({
      action,
      label: item.label,
      placeholders: item.placeholders
    });
  } else {
    result.push({
      group,
      items: [
        {
          action,
          label: item.label,
          placeholders: item.placeholders
        }
      ]
    });
  }

  return result;
}, []);

console.log(output);
newalvaro9
  • 294
  • 1
  • 7
1

Wouldn't that be a simple mapping lambda?

const input = [{
  "type": "group1@action1",
  "label": "labelA",
  "placeholders": ["b", "a", "r"]
}, {
  "type": "group1@action2",
  "label": "labelB",
  "placeholders": ["x", "y", "z"]
}, {
  "type": "group2@action123",
  "label": "labelC",
  "placeholders": ["a", "b", "c"]
}];

const inputMapped = input.map(
  item => { 
    const [group, action, label, placeholders] = 
      item.type.split(`@`).concat([item.label, item.placeholders]);
    return {
      group,
      items: { action, label, placeholders } }; } 
);

document.body.insertAdjacentHTML(`afterbegin`,
  `<pre>${JSON.stringify(inputMapped, null, 2)}</pre>`);
KooiInc
  • 119,216
  • 31
  • 141
  • 177
0

When you use Nullish coalescing assignment you can simplify your code considerably.

const input = [
  {
"type": "group1@action1",
"label": "labelA",
"placeholders": ["b", "a", "r"]
  },
  {
"type": "group1@action2",
"label": "labelB",
"placeholders": ["x", "y", "z"]
  },
  {
"type": "group2@action123",
"label": "labelC",
"placeholders": ["a", "b", "c"]
  }
];

const output = input.reduce((result, item) => {
  const [group, action] = item.type.split("@");
  result[group] ??= [];
  result[group].push({
   action,
   label: item.label,
   placeholders: item.placeholders
  });

  return result;
}, {});

console.log(output);
Thijs
  • 2,341
  • 2
  • 14
  • 22