4

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

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

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

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

我是否通过根据用户输入生成一个新数组来解决问题。或者 JavaScript 是否知道一旦到达数组末尾就循环回到数组的开头,以便将数组视为一个圆圈?

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

4

5 回答 5

2

没有现有的 Array 方法可以执行您想要的操作,但可以使用Array.prototype.sliceand轻松定义Array.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);
};

然后你可以使用lcycleandrcycle 作为普通的数组方法:

>>> 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_mandrcycle_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" ]
于 2013-02-09T14:50:36.717 回答
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
}

或沿着这条线的东西。真的没有必要创建一个新数组。

于 2013-02-09T14:45:46.957 回答
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 的一部分,因此您可能需要 polyfill,具体取决于您计划支持的浏览器。

这是一个带有一些示例的小提琴

于 2013-02-09T14:48:25.930 回答
1

这是到达数组末尾后循环回到数组开头的方法:

arr[index%arr.length],如果index> 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#"]
于 2013-02-09T15:07:54.340 回答
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);
于 2013-02-09T15:07:02.980 回答