简体   繁体   中英

Select X amount forward and backwards in an array, looping to beginning and end if needed

I need to, given an array index and a range, loop forwards X amount and backwards X amount in the array returning the new indexes.

If the loop reaches the end of the array going forwards, it continues at the beginning of the array. If the loop reaches the beginning while going backwards, it continues at the end of the array.

for example, with the array:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Given an index of 8, and a range of 3, the function would return [5, 6, 7 ,8, 9, 0, 1]

Or, given an index of 1, and a range of 3, it would return [8, 9, 0, 1, 2, 3, 4]

I tried writing a solution but it only worked for a fixed range number and was incredibly crude. Just wondering if there is a succinct way to achieve this. Javascript solution preferred, but I'm happy to translate the logic from another language if needed.

Thank you.

using modulus this is pretty easy:

var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
    index = 8,
    n = 3;

var result = [];

for (var i = index - n, len = array.length; i <= index + n; i++) {
    result.push(array[(i + len) % len]);
}

console.log(result);

Edit JSFiddle: http://jsfiddle.net/cmymS/

An explanation for the modulo operator in this example:

The modulo operator handles going over the boundaries. Inside of the for loop, i is a 'virtual' index in the array that can be less than 0 or >= len . You can think of this as having infinite repetitions of your array both on the left and right of your actual array. If i < 0 , we are accessing one of the virtual arrays to the left, if i >= len , we're accessing one of the virtual arrays to the right. The index transformation (i + len) % len then handles translating 'virtual' indices back into actual array indices.

There are two boundary conditions and the case of accessing a 'normal' index:

a) i < 0 : Consider eg i = -3 .

(i + len) will shift the position by one whole array so that we're working in the virtual array to the right, but pointing at the same element. The modulus has no effect since len - 3 is smaller than len .

b) i >= len : Consider eg i = len + 4

(i + len) will shift the position one array to the right. In our example, (i + len) will be (len + 4 + len) but the modulo neutralizes those shifts so we get 4 .

c) i is a valid index in the original array (i + len) will shift the position one array to the right, but this is reset by the modulus since 0 <= i < len . (i + len) % len = i .

function carousel(array, index, n) {
    var result = [];

    for (var i = index - n, len = array.length; i <= index + n; i++) {
        result.push(array[i < 0 ? len + i : i > len - 1 ? i - len : i]);
    }

    return result;
}

// TEST
var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
    index = 8,
    n = 3;

console.log(carousel(array, index, n));

DEMO: http://jsfiddle.net/SUGhf/

I was looking for something that will give me same thing but not only using index from array but arbitrary position that can go infinity (ie +100 - 100) so i just added one line to code above in this case -12. If someone needed it.

function carousel(array, arbitraryIndex, n) {
var result = [];
index = arbitraryIndex % (array.length);
for (var i = index - n, len = array.length; i <= index + n; i++) {
    result.push(array[i < 0 ? len + i : i > len - 1 ? i - len : i]);
}

return result;
}

var array = [0, 1, 2, 3, 4, 5],
arbitraryIndex = -12,
n = 3;

console.log(carousel(array, arbitraryIndex, n));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM