配列の並べ替え


98

たとえば、次のような配列があるとします。

var playlist = [
    {artist:"Herbie Hancock", title:"Thrust"},
    {artist:"Lalo Schifrin", title:"Shifting Gears"},
    {artist:"Faze-O", title:"Riding High"}
];

要素を別の位置に移動するにはどうすればよいですか?

例えば{artist:"Lalo Schifrin", title:"Shifting Gears"}最後に移動したいです。

私はこのようにスプライスを使ってみました:

var tmp = playlist.splice(2,1);
playlist.splice(2,0,tmp);

しかし、それは機能しません。


3
「機能しない」とはどういう意味ですか?エラーをスローしますか、何も変更しませんか?意図しない方法で配列を変更しますか?それは私には合理的に見えます。
Jacob Mattisonが2014年

回答:


220

の構文Array.spliceは次のとおりです。

yourArray.splice(index, howmany, element1, /*.....,*/ elementX);

どこ:

  • indexは、要素の削除を開始する配列内の位置です
  • howmanyは、インデックスから削除する要素の数です
  • element1、...、elementXは、位置indexから挿入する要素です。

これは、splice()渡した引数に応じて、配列内の要素の削除、要素の追加、または要素の置換に使用できることを意味します。

削除された要素の配列を返すことに注意してください。

素晴らしくて一般的なものは:

Array.prototype.move = function (from, to) {
  this.splice(to, 0, this.splice(from, 1)[0]);
};

次に、単に使用します:

var ar = [1,2,3,4,5];
ar.move(0,3);
alert(ar) // 2,3,4,1,5

図:

アルゴリズム図


17
これは良い答えであり、splice()内のsplice()がうまく機能します。ただし、move()メソッドをArrayプロトタイプに追加することは「Monkey Patching」と呼ばれ、通常は悪い習慣と見なされていることに注意してください。 stackoverflow.com/questions/5741877/...
アーロンCicali

20

インデックスがわかっている場合は、次のような単純な関数で要素を簡単に交換できます。

function swapElement(array, indexA, indexB) {
  var tmp = array[indexA];
  array[indexA] = array[indexB];
  array[indexB] = tmp;
}

swapElement(playlist, 1, 2);
// [{"artist":"Herbie Hancock","title":"Thrust"},
//  {"artist":"Faze-O","title":"Riding High"},
//  {"artist":"Lalo Schifrin","title":"Shifting Gears"}]

配列インデックスは配列オブジェクトのプロパティにすぎないため、値を交換できます。


ありがとう、@ CMS。意味を交換したくない場合は、順序を置き換えたくない...たとえば、3番目のオブジェクトを1番目の位置に選択した場合、1を2として、2を3として1として交換したい
Peri

13

ここに興味がある人のための不変バージョンがあります:

function immutableMove(arr, from, to) {
  return arr.reduce((prev, current, idx, self) => {
    if (from === to) {
      prev.push(current);
    }
    if (idx === from) {
      return prev;
    }
    if (from < to) {
      prev.push(current);
    }
    if (idx === to) {
      prev.push(self[from]);
    }
    if (from > to) {
      prev.push(current);
    }
    return prev;
  }, []);
}

こんにちは、上記の答えに対するこの機能の利点を私に説明できますか?
Xogno 2017

1
このソリューションでは、元の要素は変更されませんが、移動されたエントリを含む新しい配列が返されます。
chmanie 2017

7

要素を削除するときに、スプライス呼び出しの最初のパラメーターとして2を1に変更します。

var tmp = playlist.splice(1, 1);
playlist.splice(2, 0, tmp[0]);

1
プレイリストです。splice(2,0、tmp [0]); 正しい?
クリスブート2017年

7

ではES6あなたはこのような何かを行うことができます。

const swapPositions = (array, a ,b) => {
  [array[a], array[b]] = [array[b], array[a]]
}

let array = [1,2,3,4,5];
swapPositions(array,0,1);

/// => [2, 1, 3, 4, 5]

1
これにより、2つの要素の位置が入れ替わります。質問は再注文です。
BY

5

現在レコードがどこにあるかわからない場合は、常にsortメソッドを使用できます。

playlist.sort(function (a, b) {
    return a.artist == "Lalo Schifrin" 
               ? 1    // Move it down the list
               : 0;   // Keep it the same
});

return +(a.artist == "Lalo Schifrin")
Funkodebat

2
@Funko冗長性よりも簡潔性を優先する場合は、それを行うことができます。
アンディE

2

編集:彼の答えが最初に来たので、アンディの答えをチェックしてください、これは単に彼の拡張です

これは古い質問であることは承知していますが、含めることは価値があると思いますArray.prototype.sort()

MDNの例とリンク

var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
  return a - b;
});
console.log(numbers);

// [1, 2, 3, 4, 5]

幸いなことに、それは数字だけでは機能しません:

arr.sort([compareFunction])

compareFunction

ソート順を定義する関数を指定します。省略した場合、配列は各要素の文字列変換に従って、各文字のUnicodeコードポイント値に従って並べ替えられます。

それらを名で注文していることに気づきました。

let playlist = [
    {artist:"Herbie Hancock", title:"Thrust"},
    {artist:"Lalo Schifrin", title:"Shifting Gears"},
    {artist:"Faze-O", title:"Riding High"}
];

// sort by name
playlist.sort((a, b) => {
  if(a.artist < b.artist) { return -1; }
  if(a.artist > b.artist) { return  1; }

  // else names must be equal
  return 0;
});

ノートあなたが最後の名前によってそれらを注文したい場合、あなたはどちらかに持っているの両方のための重要なければならないことfirst_nameとしlast_name、私はXDを行うことはできませんいくつかの正規表現の魔法を、または実行

それが役に立てば幸い:)


これは、この回答の編集またはコメントにする必要があります。
Jared Smith

@JaredSmithおっと!私は彼の答えを見ませんでした。私は彼の質問を編集するのに十分なポイントや何もないので、この情報のすべてをコメントに追加するべきではないと思います。ですから、誰かが彼の質問を編集するまで、これはアンディEの答えの拡張であることを追加します(私がやるべきであるように)。
Jaacko Torus

今は大丈夫だと思います:)
Jared Smith


1

1つのアイテムを任意の位置から配列の最後に移動するだけの場合、これは機能するはずです。

function toEnd(list, position) {
    list.push(list.splice(position, 1));
    return list;
}

複数のアイテムを任意の位置から最後まで移動したい場合は、次のようにします。

function toEnd(list, from, count) {
    list.push.apply(list, list.splice(from, count));
    return list;
}

複数のアイテムを任意の位置から任意の位置に移動したい場合は、以下を試してください:

function move(list, from, count, to) {
    var args = [from > to ? to : to - count, 0];
    args.push.apply(args, list.splice(from, count));
    list.splice.apply(list, args);

    return list;
}

0

単純な可変ソリューションとして、続けて2回スプライスを呼び出すことができます。

playlist.splice(playlist.length - 1, 1, ...playlist.splice(INDEX_TO_MOVE, 1))

一方、このメソッドは変更せずに元の配列からセクションのコピーを返すため、単純な不変ソリューションではスライスを使用できます。

const copy = [...playlist.slice(0, INDEX_TO_MOVE - 1), ...playlist.slice(INDEX_TO_MOVE), ...playlist.slice(INDEX_TO_MOVE - 1, INDEX_TO_MOVE)]

-2

この方法で作業を並べ替える

 var tmpOrder = playlist[oldIndex];
    playlist.splice(oldIndex, 1);
    playlist.splice(newIndex, 0, tmpOrder);

これがうまくいくことを願っています


1
これは既存の回答に何を追加しますか?
Jared Smith
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.