skip to Main Content
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/

3

Answers


  1. 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);
    Login or Signup to reply.
  2. 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>`);
    Login or Signup to reply.
  3. 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);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search