Our transduce
function is powerful but requires a lot of boilerplate.
It would be nice if we had a way to transduce into arrays and objects without having to specify the inner reducer behaviour, i.e. how to build up values, since a given collection type will almost always have the same inner reducer.
In this lesson we'll being doing just that with an into()
helper function that will know if an array or object collection is passed in and handle each case accordingly.
Instructor: [00:01] The purpose of into helper is to figure out which inner reducer to use based on the collection type of our output. We want to be able to call into with our target collection, our transform, and the source collection.
[00:16] Notice that we're not specifying this reducer anywhere. That's what we want into to figure out by itself. Let's try and create this. We'll define into, which will take to as our target, our transform, and our collection.
[00:33] Then in here, we just want to call transduce based on this collection type. We can start by checking if it's an array. If it is an array, then we'd want to call transduce with the transform, an array reducer, our target collection as our initial seed, and our collection as our source.
[00:54] If you recall, the push reducer just takes an accumulation and a value, the accumulation being our array, pushes on the value, and returns the accumulation. We also need to handle the case where our target collection is an object. Let's check for that.
[01:10] We're going use the isPlaying object helper from Lodash here, just because doing that ourselves is nontrivial. If it is, we'll again call transduce with our transform. In here, we'll need some object reducer. Our target collection will be our seed, and we'll pass the collection as our source.
[01:32] Finally, if neither of those conditions match, let's just throw an error. We'll say just into only supports arrays and objects as to. Now, we need to define this object reducer. Let's do that up here.
[01:49] That will take some object and a value. Let's treat this as a value is an object with keys and values, and we want those keys and values to be folded into this accumulation object. To accomplish that, let's just do a shallow merge.
[02:10] That should be everything we need. Let's start by testing it out on an array. I will call into with an array as our target. For our transform, let's create a simple operation which multiplies array values by 10, and then divides them by two.
[02:27] I'll call compose, and we want two map operations. The first one, dividing by two, and the second one, multiplying by 10. Let's make this a bit more readable. For our target collection, let's just use an array with a few numbers.
[02:46] Let's check our result. We get an array with 5, 10, 15, 20. Perfect. Let's also test our object support, and build up an object with matching keys and values from an array. We'll call into again. Our target is going to be an object. We want to transform to convert values into objects.
[03:05] That will be a map operation, which will take a value and return an object with both the key and the values as value from the array. Again, an array of numbers is our source. We can see we forget a return up here. Let's add that in.
[03:22] Now, let's give this a go. As expected, we get this object back, where the keys and values match each other. Let's also filter out any array values that aren't numbers. Let's say we've got the string hello in here, and a function returning the string, world.
[03:39] We don't get an error, since in JavaScript, we can actually have functions as keys. For our purpose here, we're just interested in the numbers. Let's add that into our transform. We'll add in a call to compose, and then I'm just going to filter to only include numbers.
[03:57] This works straight away, because we're already importing isNumber from Lodash. To recap, our into helper now lets us transduce into both arrays and objects without specifying our inner reducers.