2

I've been searching for a way to do the equivalent of zipping and unzipping arrays in Javascript. I've found a way to to the zipping, but not the unzipping.

Overview:

I have two lists and the first members of the lists go together, the second members go together, etc. I would like to shuffle the lists to retain this pairing, and then end up with two separate lists once again.

In Python:

#Define shuffle function
shuffle = util.shuffle;

#Lists of adult and child animals
adult = ["cat", "dog", "chicken"]
child = ["kitty", "puppy", "chick"]

#zip them so I can shuffle while keeping pairs intact; then unzip them
animals = list(zip(adult, child))
random.shuffle(animals)
adult, child = zip(*animals)
adult = list(adult)
child = list(child)

In Javascript:

In the PsychoPy forums I found a way to do the zipping that will work in Pavlovia.

animals = []
for Idx in range(len(adult)):
     animals.append([adult[Idx],labelsWhole[Idx%len(child)]])
shuffle(animals)

Outstanding:

But now how can I do the equivalent of: adult, child = zip(*animals)?

I am aware of this similar post. However, there is only one comment mentioning "unzipping" and it won't work in PsychoPy.

Dave
  • 232
  • 1
  • 2
  • 14
  • _"I found a way to do the zipping in Javascript."_: that's not JS. – Andy Jun 07 '22 at 19:19
  • Ah okay, I didn't know. Edited. Question still stands. – Dave Jun 07 '22 at 19:24
  • https://quickref.me/unzip-an-array-of-arrays – cmgchess Jun 07 '22 at 19:28
  • @cmgchess Thank you! It doesn't seem to be working on PsychoPy. I believe because of the ES6 code. I'm going to try and find a workaround. – Dave Jun 07 '22 at 19:34
  • i dont know what psychopy is. are you running your js in python or somthing? – cmgchess Jun 07 '22 at 20:00
  • It's an experiment builder that uses python. But when the experiment gets hosted online it needs to be converted to JS (which won't work for some functions like zip). – Dave Jun 07 '22 at 21:20

3 Answers3

1

You can iterate over the zipped list and use tuple unpacking

for(const [adult,child] of zippedList)
  ....

I created a sandbox demo here

Wouter Vandenputte
  • 1,948
  • 4
  • 26
  • 50
  • Thanks for this! I'm completely new to JS but it looks from the code like you have to enter every item from the list manually? Is that right? – Dave Jun 07 '22 at 21:44
0
#Define shuffle function
shuffle = util.shuffle;

#Lists of adult and child animals
adult = ["cat", "dog", "chicken"]
child = ["kitty", "puppy", "chick"]
zipped = zip(adult, child)

#zip them so I can shuffle while keeping pairs intact; then unzip them
animals = list(zip(adult, child))
random.shuffle(animals)
adult, child = zip(*zipped)
adult = list(adult)
child = list(child)

you can also unzip the tuple in python by first making a variable containing the zip function, here i named the variable zipped. Then assign the return values to the variables using "," but this returns a tuple so you can just convert it using list(variable_name).

hope this helps

0

I'd like to add my two cents here as it popped up on my feed. Of course hopefully to help someone stumbling upon this thread later on.

Regarding zipping, your way is the clearest way to do things. That being said, you can also use Array.map:

function forZipped(first, second) {
  let zipped = [];
  for (let i = 0; i < first.length; i++)  {
    zipped.push([first[i], second[i]]);
  }
  return zipped;
}

function mapZipped(first,second) {
  return first.map((_, idx) => [first[idx], second[idx]]);
}

function recursionZipped(first,second) {
  if (first.length === 0) return [];
  return [[first[0], second[0]], ...recursionZipped(first.slice(1), second.slice(1))];
}

Similarly, for unzipping:

function forUnzipped(zip) {
  let first = [], second = [];
  for (let [a, b] of zip) {
    first.push(a);
    second.push(b);
  }
  return [first, second];
}

function reduceUnzipped(zip) {
  return zip.reduce(([first, second], [a, b]) => [[...first, a], [...second, b]], [[],[]]);
}

All working in a fiddle here.

Samuel Novelinka
  • 328
  • 3
  • 10