4

配列には、音階で可能なすべてのalltones音符が含まれています。

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

ユーザーのトーン入力を受け取り、配列の特定の要素を含むリストを作成したいと考えています。

alltones[5]またはから開始し"F"、その位置から に戻るまで、配列の 1 つおきの要素を取得してリストに入れたいとし"F"ます。配列は、まっすぐなリストというより円に似ています。ループが最後の要素に到達すると、配列がどのように動作するかが少しわかりません。

ユーザーの入力に基づいて、新しい配列を生成することで問題に取り組みますか? または、配列を円のように扱うように、最後に到達したら配列の先頭にループバックすることを JavaScript が認識している方法はありますか?

例: ユーザー入力 = F
私が求めている出力は、配列を F に戻すまで F から (2 項目ごとに) カウントすること
なので、目的の出力は次のようになります => 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);
};

そして、 通常の配列メソッドとしてlcycleandを使用できます。rcycle

>>> 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_mandを使用できます。rcycle_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

配列が最後に到達したら、配列の最初にループバックする方法は次のとおりです。

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 に答える
1

JS には円のサポートが組み込まれていないため、2 つのループで実行できます。

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メソッドを使用できます。indexOfおよびfilter(上で使用) は ECMAScript 5 の一部であるため、サポートする予定のブラウザーによってはポリフィルが必要になる場合があります。

これは、いくつかの例を含むFiddle です

于 2013-02-09T14:48:25.930 に答える
0

2つのループでそれを実行します。1つは最初のポイントの後に開始する配列メンバー用で、もう1つは最初から開始する方が良い方法です。ここで重要なのは、配列の最後で中断した場所に応じて、最初から開始することです。

次のようなジェネリック関数を作成できます

  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 に答える