0

I've got two arrays

const mp3 = ['sing.mp3','song.mp3','tune.mp3','jam.mp3',etc];
const ogg = ['sing.ogg','song.ogg','tune.ogg','jam.ogg',etc];

I need to shuffle both arrays so that they come out the same way, ex:

const mp3 = ['tune.mp3','song.mp3','jam.mp3','sing.mp3',etc];
const ogg = ['tune.ogg','song.ogg','jam.ogg','sing.ogg',etc];

There's a few posts on stackoverflow that shuffle arrays in the way I described --this one is pretty great-- but none of them demonstrate how to shuffle two arrays using Lodash.

The JavaScript methods library is known as weak, it has the sort() method but it doesn't have the shuffle() method, thus, all the answers are mixing the logic of shuffling an array & And & keeping the shuffle identical among multiple arrays. Therefore I thought that creating a separate question here would be a great idea.

and for the shuffeling part of the algorithm, I chose Lodash, since I'm using it, and it's the most popular JavaScript utilities library out there.

thnx!

Normal
  • 1,616
  • 15
  • 39
  • 2
    Instead of multiple arrays, why don't you make a single array of objects? `[{mp3: 'sing.mp3', ogg: 'sing.ogg'}, ...]`. Keeping related data together in objects almost always makes things easier. – Barmar May 13 '22 at 16:46
  • @Barmar because of an API for a library that I'm using, it forces me to specify the values in two different variables, think of `library.setMp3s()` & `library.setOggs()` – Normal May 13 '22 at 16:48
  • @Barmar indeed, I've included that recommendation in the answer I was writing as you made your comment! – Robin Zigmond May 13 '22 at 16:51
  • 1
    @Normal - even in that case you can shuffle a single array of objects and then `map` it to extract the properties into separate arrays to pass to your library function, as I've also shown in my answer. – Robin Zigmond May 13 '22 at 16:51
  • @RobinZigmond, I am the maintainer of my own library, so I can add way to accept an array of objects. Good. – Normal May 13 '22 at 16:58

1 Answers1

3

One simple approach is to just shuffle the array of indices and then use that to get both your arrays in the corresponding order:

const mp3 = ['sing.mp3','song.mp3','tune.mp3','jam.mp3'];
const ogg = ['sing.ogg','song.ogg','tune.ogg','jam.ogg'];

const indices = _.shuffle([0, 1, 2, 3]);

const shuffledMp3 = indices.map(idx => mp3[idx]);
const shuffledOgg = indices.map(idx => ogg[idx]);

console.log(shuffledMp3, shuffledOgg);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

However, you shouldn't need to do this. Your question only arises because you're storing the data in an unhelpful way. Since the elements of the two arrays are clearly linked to each other, you shouldn't store them as 2 arrays, but as a single array whose elements are objects holding both filenames as properties. This enables you to get what you want with a single shuffle:

const files = [{mp3: 'sing.mp3', ogg: 'sing.ogg'}, {mp3: 'song.mp3', ogg: 'song.ogg'}, {mp3: 'tune.mp3', ogg: 'tune.ogg'}, {mp3: 'jam.mp3', ogg: 'jam.ogg'}];

const shuffled = _.shuffle(files);

console.log(shuffled.map(file => file.mp3));
console.log(shuffled.map(file => file.ogg));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

(It's also worth noting that if all your file names are as predictably formed as in your example, even this is unnecessary - you can just store the "raw" filenames: ['sing', 'song', 'tune', 'jam'] and add whatever file extension you need at the point of needing it. But perhaps your real data is not so consistent.)

Robin Zigmond
  • 17,805
  • 2
  • 23
  • 34