在数组中向前和向后选择X量,如果需要,循环到开头和结尾

时间:2013-10-14 10:38:30

标签: javascript arrays math filter

我需要,给定一个数组索引和一个范围,循环在数组中转发X量和向后X量返回新索引。

如果循环到达数组的结尾,它将继续在数组的开头。如果循环在向后移动时到达开头,它将继续在数组的末尾。

例如,使用数组:

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

如果索引为8,范围为3,则函数将返回[5, 6, 7 ,8, 9, 0, 1]

或者,如果索引为1,范围为3,则返回[8,9,0,1,2,3,4]

我尝试过写一个解决方案,但它只适用于固定范围的数字而且非常粗糙。只是想知道是否有一种简洁的方法来实现这一目标。 Javascript解决方案更受欢迎,但如果需要,我很乐意将逻辑转换为另一种语言。

谢谢。

3 个答案:

答案 0 :(得分:2)

使用模数非常简单:

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);

编辑JSFiddle:http://jsfiddle.net/cmymS/

本例中对模运算符的解释:

模运算符处理越过边界。在for循环内部,i是数组中的“虚拟”索引,可以小于0或>= len。您可以将此视为在实际数组的左侧和右侧都有无限重复的数组。如果i < 0,我们正在访问左侧的一个虚拟阵列,如果i >= len,我们将访问右侧的一个虚拟阵列。然后,索引转换(i + len) % len处理将“虚拟”索引转换回实际的数组索引。

有两种边界条件和访问“正常”索引的情况:

a)i < 0:考虑例如i = -3

(i + len)会将位置移动一整个数组,以便我们在虚拟数组中向右工作,但指向相同的元素。由于len - 3小于len,因此模数无效。

b)i >= len:考虑例如i = len + 4

(i + len)会将位置向右移动一个数组。在我们的示例中,(i + len)将为(len + 4 + len),但模数会中和这些变化,因此我们得到4

c)i是原始数组中的有效索引 (i + len)会将位置向右移动一个数组,但这会由0 <= i < len以来的模数重置。 (i + len) % len = i

答案 1 :(得分:1)

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/

答案 2 :(得分:0)

我正在寻找能给我同样东西的东西,但不仅仅是使用数组中的索引,而且可以使用无限的任意位置(即+100 - 100),所以我在上面的代码中添加了一行代码-12。如果有人需要它。

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));