In the question Iterate a list as pair (current, next) in Python, the OP is interested in iterating a Python list as a series of current, next
pairs. I have the same problem, but I'd like to do it in JavaScript in the cleanest way possible, perhaps using lodash.
It is easy to do this with a simple for
loop, but it doesn't feel very elegant.
for (var i = 0; i < arr.length - 1; i++) {
var currentElement = arr[i];
var nextElement = arr[i + 1];
}
Lodash almost can do this:
_.forEach(_.zip(arr, _.rest(arr)), function(tuple) {
var currentElement = tuple[0];
var nextElement = tuple[1];
})
The subtle problem with this that on the last iteration, nextElement
will be undefined
.
Of course the ideal solution would simply be a pairwise
lodash function that only looped as far as necessary.
_.pairwise(arr, function(current, next) {
// do stuff
});
Are there any existing libraries that do this already? Or is there another nice way to do pairwise iteration in JavaScript that I haven't tried?
Clarification: If arr = [1, 2, 3, 4]
, then my pairwise
function would iterate as follows: [1, 2]
, [2, 3]
, [3, 4]
, not [1, 2]
, [3, 4]
. This is what the OP was asking about in the original question for Python.
Here's a simple one-liner:
Or formatted:
which logs:
In Ruby, this is called
each_cons
:It was proposed for lodash, but rejected; however, there's an each-cons module on npm:
There's also an
aperture
function in Ramda which does the same thing:Here's my approach, using
Array.prototype.shift
:This can be invoked as follows:
So to break it down:
Array.prototype.shift
directly mutates the array, so when no elements are left, length will obviously resolve to0
. This is a "falsy" value in JavaScript, so the loop will break.If
next
has been set previously, use this as the value ofcurrent
. This allows for one iteration per item so that all elements can be compared against their adjacent successor.The rest is straightforward.
Lodash does have a method that allows you to do this: https://lodash.com/docs#chunk
Here's a generic functional solution without any dependencies:
I know doesn't look nice at all but by introducing some generic utility functions we can make it look a lot nicer:
I could use
sizedArray
combined withforEach
fortimes
implementation, but that'd be an inefficient implementation. IMHO it's ok to use imperative code for such a self-explanatory function:If you're interested in more hardcore solutions, please check this answer.
Unfortunately
Array.fill
only accepts a single value, not a callback. SoArray(n).fill(array[Symbol.iterator]())
would put the same value in every position. We can get around this the following way:The final implementation:
By changing the parameter style to currying, the definition of pairwise would look a lot nicer:
And if you run this you get:
d3.js provides a built-in version of what is called in certain languages a
sliding
: