Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Nested arrays map vs forEach confusion

1549325328

Edited 1549325354
GiGs
Pro
Sheet Author
API Scripter
This question relates to a sheet worker, but it is a pure javascript problem, so I posted in the API forum because that's more likely to be seen by the scripters. I have this in a script which works fine: getSectionIDs(`repeating_${section}`, (idArray) => { const attrArray = []; fields.forEach(field => { idArray.forEach(id => { attrArray.push(`repeating_${section}_${id}_${field}`); }); }); fields is an array of attribute names in a single row of a repeating section. I thought I'd be able to create a more compact version using map, and tried this: const attrArray = idArray.map(id => fields.map(field => `repeating_${section}_${id}_${field}`)); This doest work and it took me a while to figure out what was going wrong. Instead of creating one array item for each attribute, it creates an item for each row id, with all the attributes on that row combined into a single item. How can I fix this so it works how I intend?
1549326319
The Aaron
Roll20 Production Team
API Scripter
Something like this: const attrArray = idArray.reduce( (m,id) => [...m, ...(fields.map(field => `repeating_${section}_${id}_${field}`))],[]); map() returns an array, which means you would end up building an array of arrays [[a,b,c],[a2,b2,c2],...] instead of a flat array.  Using reduce and the spread operator, you can flatten those arrays in the lower map into a single array.
1549326408
The Aaron
Roll20 Production Team
API Scripter
1549326521
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Note that the spread operator has issues with it due to the differing versions of Javascript running on the API and sheetworkers. Spread works for arrays and objects in sheetworkers, but will crash the API if you try to use it on an object. I'm pretty sure it works for arrays, but you'll want to check.
1549326577
GiGs
Pro
Sheet Author
API Scripter
That works. You truly are the scriptomancer! I almost understand that! I'm getting here :)
1549326645

Edited 1549326658
The Aaron
Roll20 Production Team
API Scripter
No problem. =D It does work for arrays in the API, Scott.  Annoyed it doesn't work for objects, because it's SUPER AWESOME!
1549326737
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Right?! I keep hoping they'll update the API JS version so I can stop using friggin _.extend().
1549327350
The Aaron
Roll20 Production Team
API Scripter
I like to think of Map() as a collection transformation.  You get a new collection where each entry is the result of calling the function on the corresponding entry in the source collection. I like to think of Reduce() as a collection creator.  You create a new collection based on information from an existing collection, but it doesn't need to have the same form as the source collection, or even be a collection at all. Written a bit more verbosely (or traditionally): const attrArray = idArray.reduce( (m,id) => { (fields.map(field => `repeating_${section}_${id}_${field}`)).forEach(a=>{ m.push(a); }); return m; },[]); Reduce() passes the previous returned value as the first argument to its function parameter (the first parameter).  The function must always return a value for the next iteration.  The second parameter to reduce is the starting value to pass as the first parameter on the first iteration.  The final returned value is the returned value from the last iteration. The classic Reduce() example is summing a list of numbers: let sum = [1,2,3,4,5].reduce( (m,v) => m+v, 0 ); The iterations are: ( 0,1) => 0+1 => 1 ( 1,2) => 1+2 => 3 ( 3,3) => 3+3 => 6 ( 6,4) => 6+4 => 10 (10,5) => 10+5 => 15 The Spread operator (...) just expands a collection into the scope where it's used. let a=[1,2,3]; let b=[4,5,6]; let c=[...a, ...b]; c is: [1,2,3,4,5,6] Hope that makes it clearer.
1549327377
The Aaron
Roll20 Production Team
API Scripter
Scott C. said: Right?! I keep hoping they'll update the API JS version so I can stop using friggin _.extend(). Well, you could start using Object.assign(). =D
1549327459

Edited 1549327511
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Well, I could, but then I couldn't complain as much ;) I totally hadn't forgotten about object.assign.
1549328089
GiGs
Pro
Sheet Author
API Scripter
Thanks for more verbose explanation, Aaron. I'm too sleepy to grasp it now (bedtime here) but I'll study it out tomorrow.
1549328209
The Aaron
Roll20 Production Team
API Scripter
No worries, I'll talk about programming as much as anyone likes. AMA. =D