Iterate an array as a pair (current, next) in JavaScript

前端 未结 13 924
情话喂你
情话喂你 2020-12-09 09:06

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 th

相关标签:
13条回答
  • 2020-12-09 09:55

    Here's my approach, using Array.prototype.shift:

    Array.prototype.pairwise = function (callback) {
        const copy = [].concat(this);
        let next, current;
    
        while (copy.length) {
            current = next ? next : copy.shift();
            next = copy.shift();
            callback(current, next);
        }
    };
    

    This can be invoked as follows:

    // output:
    1 2
    2 3
    3 4
    4 5
    5 6
    
    [1, 2, 3, 4, 5, 6].pairwise(function (current, next) {
        console.log(current, next);
    });
    

    So to break it down:

    while (this.length) {
    

    Array.prototype.shift directly mutates the array, so when no elements are left, length will obviously resolve to 0. This is a "falsy" value in JavaScript, so the loop will break.

    current = next ? next : this.shift();
    

    If next has been set previously, use this as the value of current. This allows for one iteration per item so that all elements can be compared against their adjacent successor.

    The rest is straightforward.

    0 讨论(0)
  • 2020-12-09 09:56

    Hope it helps someone! (and likes)

    arr = [1, 2, 3, 4];
    output = [];
    arr.forEach((val, index) => {
      if (index < (arr.length - 1) && (index % 2) === 0) {
        output.push([val, arr[index + 1]])
      }
    })
    
    console.log(output);

    0 讨论(0)
  • 2020-12-09 09:57

    Another solution using iterables and generator functions:

    function * pairwise (iterable) {
        const iterator = iterable[Symbol.iterator]()
        let current = iterator.next()
        let next = iterator.next()
        while (!current.done) {
            yield [current.value, next.value]
            current = next
            next = iterator.next()
        }
    }
    
    console.log(...pairwise([]))
    console.log(...pairwise(['apple']))
    console.log(...pairwise(['apple', 'orange', 'kiwi', 'banana']))
    console.log(...pairwise(new Set(['apple', 'orange', 'kiwi', 'banana'])))

    Advantages:

    • Works on all iterables, not only arrays (eg. Sets).
    • Does not create any intermediate or temporary array.
    • Lazy evaluated, works efficiently on very large iterables.
    0 讨论(0)
  • 2020-12-09 09:58

    Just make the "ugly" part into a function and then it looks nice:

    arr = [1, 2, 3, 4];
    
    function pairwise(arr, func){
        for(var i=0; i < arr.length - 1; i++){
            func(arr[i], arr[i + 1])
        }
    }
    
    pairwise(arr, function(current, next){
        console.log(current, next)
    })
    

    You can even slightly modify it to be able to make iterate all i, i+n pairs, not just the next one:

    function pairwise(arr, func, skips){
        skips = skips || 1;
        for(var i=0; i < arr.length - skips; i++){
            func(arr[i], arr[i + skips])
        }
    }
    
    pairwise([1, 2, 3, 4, 5, 6, 7], function(current,next){
        console.log(current, next) // displays (1, 3), (2, 4), (3, 5) , (4, 6), (5, 7)
    }, 2)
    
    0 讨论(0)
  • 2020-12-09 09:58

    My two cents. Basic slicing, generator version.

    function* generate_windows(array, window_size) {
        const max_base_index = array.length - window_size;
        for(let base_index = 0; base_index <= max_base_index; ++base_index) {
            yield array.slice(base_index, base_index + window_size);
        }
    }
    const windows = generate_windows([1, 2, 3, 4, 5, 6, 7, 8, 9], 3);
    for(const window of windows) {
        console.log(window);
    }
    
    0 讨论(0)
  • 2020-12-09 10:04

    In Ruby, this is called each_cons:

    (1..5).each_cons(2).to_a # => [[1, 2], [2, 3], [3, 4], [4, 5]]
    

    It was proposed for Lodash, but rejected; however, there's an each-cons module on npm:

    const eachCons = require('each-cons')
    
    eachCons([1, 2, 3, 4, 5], 2) // [[1, 2], [2, 3], [3, 4], [4, 5]]
    

    There's also an aperture function in Ramda which does the same thing:

    const R = require('ramda')
    
    R.aperture(2, [1, 2, 3, 4, 5]) // [[1, 2], [2, 3], [3, 4], [4, 5]]
    
    0 讨论(0)
提交回复
热议问题