2次元配列を列の値で並べ替える方法は?


90

JavaScriptで2次元配列を並べ替えるのを手伝ってくれる人はいますか?

次の形式のデータが含まれます。

[12, AAA]
[58, BBB]
[28, CCC]
[18, DDD]

並べ替えると、次のようになります。

[12, AAA]
[18, DDD]
[28, CCC]
[58, BBB]

つまり、基本的には、最初の列で並べ替えます。

乾杯


3
知っておくべきことはすべてここにあります:MDN
--Array.sort

1
@PramodVemulapalliの答えを受け入れてください、現在高投票されているものはすべて間違っています!
ベルギ2014

@jahroy:それは型強制ではなく、一貫した比較関数の要件についてです。
ベルギ2014

回答:


113

これは簡単です:

var a = [[12, 'AAA'], [58, 'BBB'], [28, 'CCC'],[18, 'DDD']];

a.sort(sortFunction);

function sortFunction(a, b) {
    if (a[0] === b[0]) {
        return 0;
    }
    else {
        return (a[0] < b[0]) ? -1 : 1;
    }
}

ドキュメントをお読みください

2番目の列で並べ替える場合は、次のようにします。

a.sort(compareSecondColumn);

function compareSecondColumn(a, b) {
    if (a[1] === b[1]) {
        return 0;
    }
    else {
        return (a[1] < b[1]) ? -1 : 1;
    }
}

4
実際にコードをテストしてください。jsfiddle.net/DuR4B/2。投稿したドキュメントリンクから直接:「compareFunctionが指定されていない場合、要素は文字列に変換し、辞書式(「辞書」または「電話帳」、数値ではない)順に文字列を比較することで並べ替えられます。たとえば、「80」辞書式順序では「9」の前ですが、数値ソートでは9は80の前にあります。」
イアン

3
@ Ian-その通りです。いい視点ね。シンプルさのポイントを証明するために私は興奮しすぎたと思います。私はそれをテストしましたが、完全ではありませんでした。今、私はそれを修正します...私が私の顔全体にその卵を塗りつける前に、サンプルデータがあなたのポイントを証明したことを望みます!
jahroy 2013

ハハ私は知っている、そのようなことが起こるとき私は嫌いです。見た目はとても正しいですが、内部的に何かが変更され、期待どおりに機能しません。文字列を<またはと比較するようなもの>です。とにかく、私はアップデートが好きです:)
Ian

1
@ Ash-見るのに最適な場所はドキュメントです。私はJSについて質問があるとき、私はMozillaのドキュメントのように、私はいつもグーグル機能「MDN {{FUNCTION_NAMEを}}。検索用語は次のようになり、この場合には、」「MDNのArray.sort」をもたらしますここに
jahroy 2015

1
...ドキュメントに示されているように、array.sort()メソッドは、JavaScriptでかなり一般的な引数として関数を取ります。Array.sort()メソッドは、それがそれに渡された関数をどのように処理するかを知っているように設計されています。それはその要素を比較するためにそれを使用しています。これは、関数を参照として渡す方法を示すために私が作成した本当に下手なフィドルです...申し訳ありませんが、それはとても悪いです。
jahroy 2015

66

最初の列に繰り返し値がある可能性があるため、最善のアプローチは次を使用することです。

var arr = [[12, 'AAA'], [12, 'BBB'], [12, 'CCC'],[28, 'DDD'], [18, 'CCC'],[12, 'DDD'],[18, 'CCC'],[28, 'DDD'],[28, 'DDD'],[58, 'BBB'],[68, 'BBB'],[78, 'BBB']];

arr.sort(function(a,b) {
    return a[0]-b[0]
});

これは正解です。数字の両方の桁が考慮されます。ありがとう!
ニック2015年

53

これを試して

//WITH FIRST COLUMN
arr = arr.sort(function(a,b) {
    return a[0] - b[0];
});


//WITH SECOND COLUMN
arr = arr.sort(function(a,b) {
    return a[1] - b[1];
});

注:元の回答では、コメントが誤っていると言及しているマイナス(-)ではなく、より大きい(>)が使用されていました。


8
明らかに間違った解決策に8つの賛成票がありますか?それは信じられないよ。比較関数について読み、負の値を返す必要がある場合を理解してください。
ベルギ2014

6
ベルギが述べたように、これは正しい解決策ではありません。多くの場合は機能するかもしれませんが、期待どおりに機能せず、頭をかいてしまうことがあります(私には起こりました)。問題の核心は、このソリューションの比較関数が2つの状態(true / 1、false / 0)のみを返すことですが、3つの状態(ゼロ、ゼロより大きい、およびゼロより小さい)を返す必要があります。
thdoan 2015年

1
私のために働いていませんでした。@jahroyは正解の男です
erdomester 2016

コメントを読んでいる人へのメモ:答えは1月5日に修正されました。現在は正しいです(compare関数は3つの可能な状態を返します)。
マーラー2017

@ベルギ、これを指摘してくれてありがとう。(私にとっては、IE11では正しく機能しません)そして、あなたのコメントを見るまで、私は理解できませんでした(なぜそれがクロムで機能するのか)。ありがとう!
アレックスネフスキー

12

矢印関数を使用して、2番目の文字列フィールドで並べ替える

var a = [[12, 'CCC'], [58, 'AAA'], [57, 'DDD'], [28, 'CCC'],[18, 'BBB']];
a.sort((a, b) => a[1].localeCompare(b[1]));
console.log(a)


10

私のような人なら、並べ替える列を変更するたびに各インデックスを変更する必要はありません。

function sortByColumn(a, colIndex){

    a.sort(sortFunction);

    function sortFunction(a, b) {
        if (a[colIndex] === b[colIndex]) {
            return 0;
        }
        else {
            return (a[colIndex] < b[colIndex]) ? -1 : 1;
        }
    }

    return a;
}

var sorted_a = sortByColumn(a, 2);

まったく同じ理由で自分で回答を作成した後、わずかな違いはありますが、実際には関数を返して直接並べ替えます。
olamotte 2017

3

特別なことは何もありません。配列から特定のインデックスの値を返すのにかかるコストを節約するだけです。

function sortByCol(arr, colIndex){
    arr.sort(sortFunction)
    function sortFunction(a, b) {
        a = a[colIndex]
        b = b[colIndex]
        return (a === b) ? 0 : (a < b) ? -1 : 1
    }
}
// Usage
var a = [[12, 'AAA'], [58, 'BBB'], [28, 'CCC'],[18, 'DDD']]
sortByCol(a, 0)
console.log(JSON.stringify(a))
// "[[12,"AAA"],[18,"DDD"],[28,"CCC"],[58,"BBB"]]"

この答えはここの私の答えとどう違うのですか?
チャールズクレイトン

1
1.何度も使用a[colIndex]していますが、ここでキャッチしていますa = a[colIndex]。それはより効率的です。2.異なるフ​​レーバーを使用しifて、より短くしています。3.関数のarr結果として戻ってsortByColこないので、関数を使用して別の参照を作成できません。それが役に立てば幸い!
Vikas Gautam 2017

3

一行で:

var cars = [
  {type:"Volvo", year:2016},
  {type:"Saab", year:2001},
  {type:"BMW", year:2010}
]


function myFunction() {
  return cars.sort((a, b)=> a.year - b.year)
}

3

あなたは(含まれている最初の列に基づいてソートする場合は番号の値を)、その後、これを試してみてください。

arr.sort(function(a,b){
  return a[0]-b[0]
})

2番目の列(文字列値を含む)に基づいて並べ替える場合は、次のことを試してください。

arr.sort(function(a,b){
  return a[1].charCodeAt(0)-b[1].charCodeAt(0)
})

2番目のケースのPSでは、ASCII値を比較する必要があります。

お役に立てれば。


0

私のユースケースには数十の列が含まれているため、@ jahroyの回答を少し拡張しました。(@ charles-claytonも同じ考えを持っていることに気づきました。)
並べ替えるパラメーターを渡すと、比較を行うために必要なインデックスを使用して並べ替え関数が再定義されます。

var ID_COLUMN=0
var URL_COLUMN=1

findings.sort(compareByColumnIndex(URL_COLUMN))

function compareByColumnIndex(index) {
  return function(a,b){
    if (a[index] === b[index]) {
        return 0;
    }
    else {
        return (a[index] < b[index]) ? -1 : 1;
    }
  }
}

0

charles-claytonと@ vikas-gautamの肩の上に立って、OPのように列に文字列がある場合に必要な文字列テストを追加しました。

return isNaN(a-b) ? (a === b) ? 0 : (a < b) ? -1 : 1 : a-b  ;

テストでisNaN(a-b)は、文字列を数値に強制変換できないかどうかを判断します。可能であれば、a-bテストは有効です。

厳密な等式テスト(a === b)は常にfalseを返すため、混合タイプの列をソートすると、常に面白い結果が得られることに注意してください。 ここでMDNを参照してください

これは、Google AppsScriptを使用したLoggerテストを使用した完全なスクリプトです。

function testSort(){

function sortByCol(arr, colIndex){
    arr.sort(sortFunction);
    function sortFunction(a, b) {
        a = a[colIndex];
        b = b[colIndex];
       return isNaN(a-b) ? (a === b) ? 0 : (a < b) ? -1 : 1 : a-b  ;  // test if text string - ie cannot be coerced to numbers.
       // Note that sorting a column of mixed types will always give an entertaining result as the strict equality test will always return false
       // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness

       }
}
// Usage
var a = [ [12,'12', 'AAA'],
          [12,'11', 'AAB'],
          [58,'120', 'CCC'],
          [28,'08', 'BBB'],
          [18,'80', 'DDD'],
        ]
    var arr1 = a.map(function (i){return i;}).sort();  // use map to ensure tests are not corrupted by a sort in-place.

    Logger.log("Original unsorted:\n     " + JSON.stringify(a));
    Logger.log("Vanilla sort:\n     " + JSON.stringify(arr1));
    sortByCol(a, 0);
    Logger.log("By col 0:\n     " + JSON.stringify(a));
    sortByCol(a, 1);
    Logger.log("By col 1:\n     " + JSON.stringify(a));
    sortByCol(a, 2);
    Logger.log("By col 2:\n     " + JSON.stringify(a));

/* vanilla sort returns " [
                            [12,"11","AAB"],
                            [12,"12","AAA"],
                            [18,"80","DDD"],
                            [28,"08","BBB"],
                            [58,"120","CCC"]
                          ]
   if col 0 then returns "[
                            [12,'12',"AAA"],
                            [12,'11', 'AAB'],
                            [18,'80',"DDD"],
                            [28,'08',"BBB"],
                            [58,'120',"CCC"]
                          ]"
   if col 1 then returns "[
                            [28,'08',"BBB"],
                            [12,'11', 'AAB'],
                            [12,'12',"AAA"],
                            [18,'80',"DDD"],
                            [58,'120',"CCC"],

                          ]"
   if col 2 then returns "[
                            [12,'12',"AAA"],
                            [12,'11', 'AAB'],
                            [28,'08',"BBB"],
                            [58,'120',"CCC"],
                            [18,'80',"DDD"],
                          ]"
*/

}

関心の可能性の更新-2019年7月2日。並べ替えが「安定」になりました。ここを読んでください。(Mathias BynensVerified @mathias経由)v8.dev/features/stable-sort
DeeKay7 8919
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.