Javascript循环行为

时间:2013-02-09 14:34:09

标签: javascript arrays loops theory

alltones数组包含音乐音阶中的所有可能音符。

var alltones = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ];

我想获取用户输入的音调,然后构造一个包含数组元素的列表。

假设我从alltones[5]"F"开始,并希望从该点获取数组的每个第二个元素并将其放入我的列表中,直到我回到"F" 。该数组更像是一个圆而不是直列表。一旦循环到达最后一个元素,我就不太确定数组是如何运作的。

我是否可以根据用户输入生成新数组来解决问题。或者有没有一种方法可以让JavaScript知道在数组到达末尾时循环回到数组的开头,这样它就像将数组视为一个圆圈一样?

一个例子: 用户输入= F
我正在寻找的输出是从F计算(每两个项目),直到我们回到数组到F
所以期望的输出将是=> F G A B C#D#

5 个答案:

答案 0 :(得分:2)

没有existing Array method可以执行您想要的操作,但可以使用Array.prototype.sliceArray.prototype.concat轻松定义一个:

// move i elements from the start of the array to the end of the array
Array.prototype.lcycle = function(i) {
  var xs = this.slice(0,i);
  var ys = this.slice(i);
  return ys.concat(xs)
};
// move i elements from the end of the array to the start of the array
Array.prototype.rcycle = function(i) {
  var xs = this.slice(0,-i);
  var ys = this.slice(-i);
  return ys.concat(xs);
};

然后您可以使用lcyclercycle作为常规数组方法:

>>> alltones.lcycle(3)
[ "D#" , "E" , "F" , "F#" , "G" , "G#" , "A" , "A#" , "B" , "C" , "C#" , "D" ]
>>> alltones.rcycle(4)
[ "G#" , "A" , "A#" , "B" , "C" , "C#" , "D" , "D#" , "E" , "F" , "F#" , "G" ]

请注意,这两个方法都返回一个新数组。如果您想改变原始数组,可以使用Array.prototype.splice定义类似的方法。

// move i elements from the start of the array to the end of the array, mutating the original array
Array.prototype.lcycle_m = function(i) {
  var args = this.splice(0,i);
  args.unshift(0);
  args.unshift(this.length);
  this.splice.apply(this, args);
};
// move i elements from the end of the array to the start of the array, mutating the original array
Array.prototype.rcycle_m = function(i) {
  var args = this.splice(-i);
  args.unshift(0);
  args.unshift(0);
  this.splice.apply(this, args);
};

同样,您可以使用lcycle_mrcycle_m作为常规数组方法:

>>> alltones.lcycle_m(3)
>>> alltones
[ "D#" , "E" , "F" , "F#" , "G" , "G#" , "A" , "A#" , "B" , "C" , "C#" , "D" ]
>>> alltones.rcycle_m(3)
>>> alltones
[ "C" , "C#" , "D" , "D#" , "E" , "F" , "F#" , "G" , "G#" , "A" , "A#" , "B" ]

答案 1 :(得分:1)

你可以在两个循环中完成,因为JS没有内置的支持圈。

for (var i = users_input; i < alltones.length; i += 1) {
  ... use alltones[i] for calc
}
for (var i = 0; i < users_input; i += 1) {
  ... use alltones[i] for calc
}

或那条线上的东西。 实际上不需要创建新阵列。

答案 2 :(得分:1)

这个怎么样:

function getNotes(index) {
  var list = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ];
  return list.splice(index).concat(list).filter(function(note, i) {
    return i % 2 == 0;
  });
}
getNotes(3); // ["D#", "F", "G", "A", "B", "C#"]

这样做首先重新组织数组,以便将所选索引转移到开头,并将之前的所有内容移动到结尾,然后过滤掉所有其他注释。如果您希望getNotes函数使用字符串,则可以使用indexOf方法。 indexOffilter(上面使用过的)是ECMAScript 5的一部分,因此您可能需要根据您计划支持的浏览器进行填充。

这是Fiddle with some examples

答案 3 :(得分:1)

这是在数组到达结尾时循环回到数组开头的方法:

arr[index%arr.length],如果index&gt; arr.length,它将“循环”到开头。

这种技术很有效,适用于几乎所有语言。

var alltones = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ];

function generateMusic(startIndex) {
    var i = 0, music = [],
        tonesCount = alltones.length

    do { 
        music.push(alltones[(startIndex+i)%tonesCount]); 
    } while ((i+=2) < tonesCount);

    return music;
}

结果:

console.log(generateMusic(3)); //["D#", "F", "G", "A", "B", "C#"]
console.log(generateMusic(5)); //["F", "G", "A", "B", "C#", "D#"]

答案 4 :(得分:0)

在两个循环中执行一个数组成员从初始点开始,另一个从头开始是更好的方法;这里的关键是从头开始,取决于我们在数组末尾的位置。

你可以创建像

这样的通用函数
  var alltones = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ];

  function build_tones(arr, start, jump_by){

  var new_list = [];

           //finish first iteration and get the last index so that we can offset accordingly from the beginning
             var get_last = (function(){
               var last;
              for(i = start; i <= arr.length; i+=jump_by){
                new_list.push(arr[i]);
                last = i;
                }
              return last;
              })();

     //do the second iteration by picking up from the index left and continue from first

    for(i = 0 + arr.length%get_last; i < start; i+=jump_by){
    new_list.push(arr[i]);
    }

    return new_list;

  }

 var result = build_tones(alltones, 5, 2);
 console.log(result);