Search code examples
javascriptarraysfunctional-programmingimmutability

Functional immutable way in javascript to copy an array with additional items in certain positions depending on condition on items


I have an array:

[
    { "name": "batman", "hasSidekick": true },
    { "name": "shazam!", "hasSidekick": false },
    { "name": "capt america", "hasSidekick": true },
    { "name": "spiderman", "hasSidekick": false }
]

From this, I want to create a new array of hero names which will have all of the above names but when hasSidekick is true for a hero, there should be an additional name inserted after it.

Expected output:

[
    "batman",
    "batman's sidekick",
    "shazam!", ,
    "capt america",
    "capt america's sidekick",
    "spiderman"
]

I can do it with forEach and pushing additional items conditionally based on hasSidekick:

const heroes = [
  { name: "batman", hasSidekick: true },
  { name: "shazam!", hasSidekick: false },
  { name: "capt america", hasSidekick: true },
  { name: "spiderman", hasSidekick: false },
];
let heroesAndSidekicks = [];
heroes.forEach(hero => {
  heroesAndSidekicks.push(hero.name);
  if (hero.hasSidekick) {
    heroesAndSidekicks.push(`${hero.name}'s sidekick`);
  }
});
console.log(heroesAndSidekicks);

But please suggest how I can do it in functional programming way without mutation.


Solution

  • You could take Array#flatMap.

    var data = [{ name: "batman", hasSidekick: true }, { name: "shazam!", hasSidekick: false }, { name: "capt america", hasSidekick: true }, { name: "spiderman", hasSidekick: false }],
        result = data.flatMap(({ name, hasSidekick }) => hasSidekick
            ? [name, name + '\'s sidekick']
            : name
        );
    
    console.log(result);