0

I have an array of different exercises:

exercises: {
  push: ['Push up', 'Bench press'],
  legs: ['Squat', 'Power squats'],
  pull: ['Pull up', 'Chin up'],
  cardioCore: ['Running high knees', 'Plank']
}

How can I combine all of these into a single array or object? I need to create this:

allExercises: ['Push up', 'Bench press', 'Squat', 'Power squats', 'Pull up', 'Chin up', 'Running high knees', 'Plank']  

I'm also going to sort alphabetically so the order isn't important.

I think I could do this with a forEach, something like this:

let allExercises = [];
exercises.forEach(exerciseGroup=>{
  allExercises.push(exerciseGroup);
});

But this feels a bit messy. Is there a nicer ES6 solution?

1
  • Use .concat(). Commented Nov 7, 2017 at 3:43

5 Answers 5

2

Yes, just use Object.values and Array.prototype.reduce.

const allExercises = Object.values(exercises)
  .reduce((array, subarray) => array.concat(subarray), []);
Sign up to request clarification or add additional context in comments.

4 Comments

Personal preference, but instead of .concat function, one can also use the ... (spread) operator
Also, is Object.values part of ES6 or ES7, just curious
@AyushGupta Hm… it’s actually ES8, but it can easily be polyfilled or replaced by a Object.keys approach.
Yeah, was just curious because this call once failed in node 6.10 xD
2

Here's another way, ES6 compatible.:

Object.getOwnPropertyNames(exercises)
.reduce((allExercises, exerciseName) => [...allExercises, ...(exercises[exerciseName])], [])

As @stealththeninja said, you can also do this to reduce a bunch of overhead.

Object.getOwnPropertyNames(exercises).reduce((allExercises, exerciseName) => {
  allExercises.push(...exercises[exerciseName]);
  return allExercises;
}, []);

5 Comments

[...all, ...exercises[name] returns a new array each time. Reduce passes the object (or array) by reference, why not add the items and return all? all.push(...exercises[name]); return all;
You could, I just prefer the spread approach. One liner returns seem cleaner.
One liner returns seem cleaner. Cleaner syntactically but wasteful creating a new array for each property name.
Hmm, yeah. Edited the answer to add your suggestion as an alternative, thanks!
Thanks for considering the feedback, I appreciate it. :)
0

My ugly solution:

  let combineExercises = [];

  Object.values(allExercises).forEach((exerciseGroup) => {
    exerciseGroup.forEach((exercise) => {
      combineExercises.push(exercise)
    })
  });

  console.log(combineExercises);

Comments

0

You can use Object.values & spread operator

var exercises = {
    push: ['Push up', 'Bench press'],
    legs: ['Squat', 'Power squats'],
    pull: ['Pull up', 'Chin up'],
    cardioCore: ['Running high knees', 'Plank']
}
var allexercise ={},tempArray=[];
for(var keys in exercises){

    tempArray.push(...Object.values(exercises[keys]))
}
allexercise=tempArray;

console.log(allexercise)

Comments

0
[].concat.apply([], Object.values(exercises));

7 Comments

What's the need for .join(',').split(',')?
.join joins nested arrays as if they are flat. [[1,2,3], [2,3,4], 5].join(',') will yeild 1,2,3,2,3,4,5
@Xufox yes won't work if there is a comma in the exercise
Xufox raises a valid test case where the join/split fails. We might use spread syntax (...) but it's still unnecessarily more complex than using Object#values and Array#reduce.
That last approach is actually really elegant.
|

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.