1

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.

10
  • You can do it with Array.prototype.reduce. Commented Jan 15, 2020 at 20:50
  • 1
    what do you mean "without mutation"? I'm just confused why you need that? Commented Jan 15, 2020 at 20:52
  • Use Array.prototype.concat to combine the results from each iteration. The results from each iteration should be an array with 1 element or 2 elements, depending on whether the hero has a sidekick. Commented Jan 15, 2020 at 20:53
  • 1
    Wouldn't you need at least some mutation if you want add items to your array? There is no adding or removing without changing something. Or do you mean without mutating the original array? Commented Jan 15, 2020 at 20:57
  • 1
    I am also confused by the "without mutation" requirement. You want to create a new array right? Well that new array is going to start out empty and in order to get elements into it you are going to have to "mutate" it. Commented Jan 15, 2020 at 20:58

2 Answers 2

4

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);

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

1 Comment

Thank you! The flatmap will flatten out if an array is returned. This is fantastic!
1

I think Array.prototype.reduce() can solve your issue. From the documentation:

The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.

Please find a possible solution below:

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

const result = data.reduce((a, e) => {
  a.push(e.name);

  if (e.hasSidekick) {
     a.push(`${e.name}'s sidekick`);
  }

  return a;
}, []);

console.log(result);

I hope that helps!

1 Comment

a.push() is mutation.

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.