问题 在JavaScript中循环读取数组值


我在JavaScript中有一个定义了这些值的数组:

var myStringArray = ["1","2","3","4","5","6","7","8","9","10"];

当我第一次调用函数时,我需要得到这个:

1
2
3

再次打电话给我需要得到:

4
5
6

再次打电话:

7
8
9

再次打电话:

10
1
2

再次打电话:

3
4
5

等等。你明白了,从数组中显示3个值,如果我们在数组末尾,请从头开始阅读...我有一个具有远程控制功能的应用程序,并且具有向下和向上键。当用户按下向下按钮从数组中获取这些值时,如上例所示,如果用户按下向上按钮,则需要从示例返回...所以在循环中读取数组(最后,数组从头开始读取,但始终显示三个值)。

我尝试使用这个:

var myStringArray = ["1","2","3","4","5","6","7","8","9","10"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
    if (i<(6)) {
       console.log(myStringArray[i]);
    }
}

但是下次我调用这段代码时,它会从数组的开头显示,而不是继续读取其他值...我需要第二个计数器吗?


982
2018-05-22 13:37


起源

显示你到目前为止所尝试的内容。 StackOverflow不是我们为您的学校项目提供直接和完整答案的地方。提示:使用闭包来保存函数内的状态。 - soueuls
谢谢我知道这不是给我写代码的地方..但我真的不知道如何将循环阅读归档...所以只有当我<6和第二个计数器并且效率不高时才能用很多方式...谢谢你的表现...... - Igor Petev
闭包是函数内部的函数。它允许您冻结调用之间的变量值。然后你可以冻结你的价值 i 并从这里构建逻辑。这只是以循环方式循环3次的问题。 - soueuls


答案:


如果您可以在循环浏览原始数组时操作它 splice 和 concat 类似于下面(或者你可以使用数组的克隆,如果你需要保持原始数组):

var myStringArray = ["1","2","3","4","5","6","7","8","9","10"];

var loopByX = function(x){
  var y = myStringArray.splice(0,x);
  myStringArray = myStringArray.concat(y);
  
  return y;
}

console.log(loopByX(3));
console.log(loopByX(3));
console.log(loopByX(3));
console.log(loopByX(3));
console.log(loopByX(3));

如果你想要双向(就是你所说的那个?),正如评论中所提到的那样,你可以按照下面的方式进行,然后让你能够前进或前进,并且可以灵活地进行任意操作。数:

var myStringArray = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];

var loopByX = function(x) {
  var len = myStringArray.length;

  // Ensure x is always valid but you can add any behaviour here in that case yourself. As an example I return an empty array.
  if (Math.abs(x) > len) {
    return [];
  }

  var y = x > 0 ? myStringArray.splice(0, x) : myStringArray.splice(len + x, len);

  myStringArray = x > 0 ? myStringArray.concat(y) : y.concat(myStringArray);

  return y;
}

console.log(loopByX(20)); // invalid number
console.log(loopByX(-20)); // invalid number
console.log(loopByX(-3));
console.log(loopByX(-6));
console.log(loopByX(3));
console.log(loopByX(4));


9
2018-05-22 13:44



如果你这样做 myStringArray = x > 0 ? myStringArray.concat(y) : y.concat(myStringArray) 它也会倒退 - Jonas Wilms
这是一个有趣的解决方案。 - Mihai Alexandru-Ionut
非常有趣的代码......你能用x> 0给出例子#2吗?当你发表评论?我尝试在jsfiddle,但我总是错误未捕获ReferenceError:x未定义 - Igor Petev
我添加了反转示例和一些基本验证使用 Math.abs(x) 但你可以根据自己的需要进行调整。 - Nope
我非常喜欢这个功能...它按预期工作...并且非常有效...现在我试图返回每个数字<div> </ div>,因为我的应用程序使用jQuery插入我尝试使用此代码:$(“。mm_vert_container”)。append(“<div>”+(temp.concat(temp.length <6?tv.slice(0,ch):[])。join(''))+ “</ DIV>”);但我需要玩一点 - Igor Petev


你可以采用一个切三个元素的函数,如果不可能的话,它也需要数组所需的第一个值。

function take3() {
    var temp = array.slice(index, index += 3)
    index %= array.length;
    console.log(temp.concat(temp.length < 3 ? array.slice(0, index) : []).join(' '));
}

var array = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
    index = 0;
<button onclick="take3()">take 3</button>

使用动态计数的映射。

function take(length) {
    console.log(Array.from({ length }, _ => array[++index, index %= array.length]));
}

var array = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
    index = -1;
<button onclick="take(3)">take 3</button>


4
2018-05-22 13:47



我也喜欢这个答案。 - Mihai Alexandru-Ionut
非常好的代码.... - Igor Petev


你的变量 i 是当地的 for 循环,这意味着它每次循环启动时基本上都会重置。所以首先要做你的变量 i 全球。

var i=0;
function employeeNames(){
    var empList =  ["1","2","3","4","5","6","7","8","9","10"];
    var output = [];
    var j=0;
    while(j<3)
    {
        output.push(empList[i])
        i=(i+1)%empList.length;
        j++;
    }
    return output;
}

console.log(employeeNames());
console.log(employeeNames());
console.log(employeeNames());
console.log(employeeNames());
console.log(employeeNames());


2
2018-05-22 13:51



全球好吗? - Peter Mortensen


如果您希望以不可变的方式实现循环循环

function loopArray(arr, step=3) {
    let i = 0;
    return function inner() {
        for (let j = 0; j < step; j++) {
            console.log(arr[i]);
            i = (i + 1) % arr.length;
        }
    };
 }

const func = loopArray(["1","2","3","4","5","6","7","8","9","10"], 3);
func();
func();
func();
func();
func();

1
2018-05-22 14:04





具有发电机功能的奇特解决方案:

function* cycle(arr) {
    let i=0;
    while (true) {
        yield arr[i++];
        i %= arr.length;
    }
}
function* chunksOf(n, iterable) {
    let chunk = [];
    for (const x of iterable) {
        chunk.push(x)
        if (chunk.length >= n) {
            yield chunk;
            chunk = [];
        }
    }
    if (chunk.length > 0)
        yield chunk;
}
function toFunction(iterator) {
    return () => iterator.next().value;
}
var myStringArray = ["1","2","3","4","5","6","7","8","9","10"];

const f = toFunction(chunksOf(3, cycle(myStringArray)));
console.log(f());
console.log(f());
console.log(f());
// …

1
2018-05-22 17:16





@Igor Petev,JavaScript的闭包是一个很好的概念,可以用来解决你的问题。

请阅读 JavaScript的闭包 - w3schools 文章。它非常好,非常好。

我已经使用闭包的概念来解决这个问题。如果您不理解我的代码或与此问题相关的任何其他内容,请发表评论。

请看下面的代码。

var get3items = (function () {

    var index = 0;
    var myStringArray = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
    var len = myStringArray.length

    return function () {
       for(var count = 0; count < 3; count += 1)
       {
           console.log(myStringArray[index]);

           if(index == (len - 1))
           {
               index = 0;
           }
           else {
               index += 1;
           }
       }
    }
})();

get3items (); // First call

console.log()
get3items (); // Second call

console.log()
get3items (); // Third call

console.log()
get3items (); // Fourth call

console.log()
get3items (); // Fifth call

/*
 1
 2
 3

 4
 5
 6

 7
 8
 9

 10
 1
 2

 3
 4
 5
*/

1
2018-05-22 14:27



感谢另一个非常好的解决方案...感谢发布我将学习示例,并记住当我需要它在feauture项目 - Igor Petev
没问题,享受JavaScript。不错的问题,我第一次使用JavaScript的闭包来回答stackoverflow上的任何问题,并且它被接受了。谢谢。 - hygull


如何使用发电机:

function* get3() {
  var myStringArray = ["1","2","3","4","5","6","7","8","9","10"];
  var index = 0;
  while (true) {
    yield [0, 1, 2].map(i => myStringArray[(index + i) % myStringArray.length])
    index = (index + 3) % myStringArray.length;
  }
}

调用此函数会返回一个可以调用的对象 .next() 在,获得下一组3:

var getter = get3();
console.log(getter.next().value); // ["1","2","3"]
console.log(getter.next().value); // ["4","5","6"]
console.log(getter.next().value); // ["7","8","9"]
// etc.

0
2018-05-22 17:08





您需要一个额外的指针,以识别您在数组中的位置。

要从头开始,当你到达数组的末尾时,可以使用模运算符。

var myStringArray = ["1","2","3","4","5","6","7","8","9","10"];
var arrayLength = myStringArray.length;
var arrayPointer = 0;
for (var i = 0; i < 3; i++) {
    console.log(myStringArray[arrayPointer++]);
    arrayPointer %= arrayLength; // same as: arrayPointer = arrayPointer % arrayLength;
}

看看Akshay Garg的答案,看看如何将它包装在一个函数中。


-1
2018-05-22 13:58





function* employeeNames(){
    var empList =  ["1","2","3","4","5","6","7","8","9","10"];

    for(var i =0; i<=empList.length; i++){
        yield empList[i];
    }
}

var emp;
emp = employeeNames();

它使用发电机功能......


-2
2018-05-22 13:42



你试过这段代码吗? - Mihai Alexandru-Ionut
使用生成器函数是一个简洁的解决方案,但此代码无法解决问题 - Christopher Moore
此代码没有给出我在上面发布的示例中所需的内容..但感谢您的回答.. - Igor Petev
是的,我只是给了你一个主意 - anshuVersatile
谢谢......我知道了 - Igor Petev