Array.reduce on a multidimensional array to array of objects
Solution 1
You have to be thinking about the shape of your input data (DATA
) and output (DATA'
)
Note 1:1 relationship between HAND
and HAND'
meaning we will use Array.prototype.map
for one transformation. On the other hand, CARD
has a N:1 relationship with HAND'
meaing we will use Array.prototype.reduce
for that transformation
So keep in mind while we're working, we will be doing a map and a reduce
const data =
[ [ { value: 5, suit: 's' },
{ value: 4, suit: 's' },
{ value: 6, suit: 'c' },
{ value: 11, suit: 'd' },
{ value: 12, suit: 'c' } ],
[ { value: 9, suit: 'd' },
{ value: 12, suit: 'h' },
{ value: 8, suit: 'c' },
{ value: 12, suit: 's' },
{ value: 2, suit: 's' } ],
[ { value: 4, suit: 'h' },
{ value: 6, suit: 's' },
{ value: 10, suit: 'c' },
{ value: 3, suit: 'd' },
{ value: 7, suit: 'd' } ] ]
let output =
data.map(cards =>
cards.reduce(({values, suits}, {value, suit}) => ({
values: [...values, value],
suits: [...suits, suit]
}), {values: [], suits: []}))
console.log(output)
Now of course that looks a little dense so it would be nice if we could dial down the complexity a bit. By making some curried adapters for map
and reduce
we can express a function that performs your transformation quite nicely
const data =
[ [ { value: 5, suit: 's' },
{ value: 4, suit: 's' },
{ value: 6, suit: 'c' },
{ value: 11, suit: 'd' },
{ value: 12, suit: 'c' } ],
[ { value: 9, suit: 'd' },
{ value: 12, suit: 'h' },
{ value: 8, suit: 'c' },
{ value: 12, suit: 's' },
{ value: 2, suit: 's' } ],
[ { value: 4, suit: 'h' },
{ value: 6, suit: 's' },
{ value: 10, suit: 'c' },
{ value: 3, suit: 'd' },
{ value: 7, suit: 'd' } ] ]
const map = f => xs => xs.map(f)
const reduce = f => y => xs => xs.reduce(f, y)
const handAppendCard = ({values, suits}, {value, suit}) => ({
values: [...values, value],
suits: [...suits, suit]
})
const makeHands =
map (reduce (handAppendCard) ({values:[], suits:[]}))
let output = makeHands (data)
console.log(output)
That's just one way to approach the problem. I hope you were able to learn something from it ^_^
Solution 2
There you go - a solution using nested Array.prototype.reduce
functions:
var array=[[{value:5,suit:'s'},{value:4,suit:'s'},{value:6,suit:'c'},{value:11,suit:'d'},{value:12,suit:'c'}],[{value:9,suit:'d'},{value:12,suit:'h'},{value:8,suit:'c'},{value:12,suit:'s'},{value:2,suit:'s'}],[{value:4,suit:'h'},{value:6,suit:'s'},{value:10,suit:'c'},{value:3,suit:'d'},{value:7,suit:'d'}]];
var result = array.reduce(function(p, c) {
p.push(c.reduce(function(a, b) {
a.values.push(b.value);
a.suits.push(b.suit);
return a;
}, {values: [],suits: []}));
return p;
},[]);
console.log(result);
.as-console-wrapper {top: 0;max-height: 100%!important;}
Related videos on Youtube
Comments
-
Jackson Lenhart almost 2 years
In my poker app I have an array of hands, each hand being array of randomly selected card objects with value and suit:
[ [ { value: 5, suit: 's' }, { value: 4, suit: 's' }, { value: 6, suit: 'c' }, { value: 11, suit: 'd' }, { value: 12, suit: 'c' } ], [ { value: 9, suit: 'd' }, { value: 12, suit: 'h' }, { value: 8, suit: 'c' }, { value: 12, suit: 's' }, { value: 2, suit: 's' } ], [ { value: 4, suit: 'h' }, { value: 6, suit: 's' }, { value: 10, suit: 'c' }, { value: 3, suit: 'd' }, { value: 7, suit: 'd' } ] ]
To prepare the hands for evaluation I want to use Array.reduce to return an array of hand objects. So the output would be:
[ { values: [5, 4, 6, 11, 12], suits: ['s', 's', 'c', 'd', 'c'] }, { values: [9, 12, 8, 12, 2], suits: ['d', 'h', 'c', 's', 's'] }, { values: [4, 6, 10, 3, 7], suits: ['h', 's', 'c', 'd', 'd'] } ]
I tried implementing this with nested forEach's, but its failing and I don't know why. I have two console.log's within which output as expected, but in the end hands is identical to the input.
let temp = [] hands.forEach((el) => { temp = el el = {} el.values = [] el.suits = [] console.log(el) //expected output temp.forEach((obj) => { el.values.push(obj.value) el.suits.push(obj.suit) console.log(el) //expected output }) }) console.log(hands) //same as original
-
charlietfl over 7 years"I want to use reduce" ... so where is your code attempt to do so? This isn't a code writing service. This site works by you posting your code that isn't working as expected and people help you fix that
-
Jackson Lenhart over 7 yearsI made code attempts, I didn't think they would be helpful to post because it seemed any valid answer would be a complete rewrite of my implementation. Fair criticism though, I'll keep it in mind.
-
Barmar over 7 yearsWhy does this have to be done using
reduce
? It seems like it would be simpler usingforEach
. -
Barmar over 7 years
el
is a variable local to the function, it gets reset to{}
each time through theforEach
loop. Your code never modifieshands
.
-
-
Barmar over 7 yearsHe wants arrays in his result, not concatenated strings.
-
Nishanth Matha over 7 years@Barmar thanks for the comment...edited the post to reflect the changes
-
Barmar over 7 yearsThat's a silly fix. Why make a string and then split up into an array when you can just create an array in the first place?
-
Nishanth Matha over 7 years@Barmar that's a fair comment. See the edit 2 and just bring on what you got :D ...