質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.99%

2次元配列を特定の要素でグルーピングし、3次元配列に組み直す

解決済

回答 5

投稿

  • 評価
  • クリップ 1
  • VIEW 2,347

true

score 429

いま、下記コードに示すような2次元配列aryがあり、ary2はaryについて関東、東海、北陸でグルーピングしたときの各グループの個数を示しています。これらはGASのスプレッドシート上からQUERY関数等を駆使して2次元配列を取得しており、通常のSQL段階での加工は諦め、JavaScript上でこの作業をやるハメになっているという前提です。

強引かもしれませんが、下記コードで実現しました。が、どうも無駄が多いような気がするので別解があればよろしくお願い致します。たとえばary2って不要な気もしますし。いつも要領の悪いコードで恐縮です。

  var ary = [];
  var ary2 = [];
  var ary3 = [];
  var ary4 = [];
  var k = 0;
  ary = [["関東", "東京"],["関東","神奈川"],["関東","千葉"],["関東","埼玉"],["東海","愛知"],["東海","三重"],["東海","岐阜"],["北陸","富山"],["北陸","福井"],["北陸","石川"]];
  ary2 = [["関東",4],["東海",3],["北陸",3]];
  
  
  for (var i=0; i<ary2.length; i++) {
    for (var j=0; j<ary2[i][1]; j++) {
      ary3.push(ary[k]);
      k++;
    }
    ary4.push(ary3);
    ary3 = [];
  }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+4

私はご提示のコードで十分だと思います。

考えてみましたが、以下のようなわけのわからないコードになってしまいました。
(ary2を使わない方法)
var ary = [["関東", "東京"],["関東","神奈川"],["関東","千葉"],["関東","埼玉"],["東海","愛知"],["東海","三重"],["東海","岐阜"],["北陸","富山"],["北陸","福井"],["北陸","石川"]];
var ary2 = new Array();
var ary3 = new Array();
var var k = 0;
for(var i = 0; i < ary.length; i++){
    if(ary2[ary[i][0]] == null){
        ary2[ary[i][0]] = k++;
    }
    if(ary3[ary2[ary[i][0]]] == null){
        ary3[ary2[ary[i][0]]] = new Array();
    }
    ary3[ary2[ary[i][0]]][ary3[ary2[ary[i][0]]].length] = ary[i];
}

もしも処理結果が連想配列でもいいのであれば、さらに変数が減らせます。
var ary = [["関東", "東京"],["関東","神奈川"],["関東","千葉"],["関東","埼玉"],["東海","愛知"],["東海","三重"],["東海","岐阜"],["北陸","富山"],["北陸","福井"],["北陸","石川"]];
var ary2 = new Array();
for(var i = 0; i < ary.length; i++){
    if(ary2[ary[i][0]] == null){
        ary2[ary[i][0]] = new Array();
    }
    ary2[ary[i][0]][ary2[ary[i][0]].length] = ary[i];
}

連想配列を普通の配列に戻す
var ary = [["関東", "東京"],["関東","神奈川"],["関東","千葉"],["関東","埼玉"],["東海","愛知"],["東海","三重"],["東海","岐阜"],["北陸","富山"],["北陸","福井"],["北陸","石川"]];
var ary2 = new Array();
var ary3 = new Array();
for(var i = 0; i < ary.length; i++){
    if(ary2[ary[i][0]] == null){
        ary2[ary[i][0]] = new Array();
    }
    ary2[ary[i][0]][ary2[ary[i][0]].length] = ary[i];
}
for(var key in ary2){
    ary3[ary3.length] = ary2[key];
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/27 15:31 編集

    賛同します.私も連想配列を使うほうがコードが綺麗になるので,好んで使います.連想配列を使うことのオーバヘッドなんてそんなに大きなものではないので.
    このコードが何万回も実行されてパフォーマンスボトルネックになる,という場合以外は,アルゴリズムとして高速であるよりは,コードが明快で簡潔であるほうが重視されると思います.後々のデバッグのためになりますし,プログラムを書くコストを減らすことができるので.

    キャンセル

  • 2015/11/27 17:34

    ありがとうございます。たとえばary2["関東"]とやると関東グループにアクセスできるということですね。こうゆう使い方には慣れていないので勉強させて頂きます。これがコード的には一番すっきりしますね。じっくり拝見させて頂きます。

    キャンセル

+1

そのコードで問題ないような気がしますが、ちょっと書いてみました。
  dict={}
  ary.forEach(function(x){
    x[0] in dict ? dict[x[0]].push(x) : dict[x[0]] = [x];
  });
  Object.keys(dict).map(function(x){
    return dict[x];
  })

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

関東だとかregion_nameが乱雑に出現しないならこれでもいける。

var ary = [["関東", "東京"],["関東","神奈川"],["関東","千葉"],["関東","埼玉"],["東海","愛知"],["東海","三重"],["東海","岐阜"],["北陸","富山"],["北陸","福井"],["北陸","石川"]];
var ary2 = new Array();
var region_name = '';

for(var k=0; k < ary.length; k++){
    
    if(ary[k][0] != region_name){
        region_name = ary[k][0];
        ary2.push(new Array());
    }
    
    ary2[ary2.length-1].push(ary[k]);
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/27 17:28

    ありがとうございます。私もロジックとしては前後のregionを比較しながら・・と思いついたのですが具体的にどう書けばいいのかが分かりませんでした。参考にさせて頂きます。

    キャンセル

+1

ついでにもうひとつ。
副作用なしを目指してみました。
  ary.map(function(x){
    return x[0];
  })
  .filter(function(x, i, self){
    return i == self.indexOf(x);
  })
  .map(function(x){
    return ary.filter(function(y){
      return y[0] == x;
    });
  });

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/27 17:26

    ありがとうございます。とてもモダンで興味深いのですが各要素へのアクセスのしかたが分かりませんでした。たとえば関東グループへのアクセスはary[0]とか?ではないですよね。すみません、ついていけませんでした。

    キャンセル

  • 2015/11/27 18:08

    分かりにくくてすみません。戻り値がそのまま結果になっています。
    頭に ary4 = などとつけて代入してみてください。

    キャンセル

  • 2015/11/27 23:31

    ありがとうございます。できました!そうやって使うのですね。メソッドチェーンでこんな風につなげられることもすごいと思いました。

    キャンセル

+1

Ramdaを使っていいのであれば、一行で書けます。
'use strict';
var R = require('ramda');
var ary;
var ary4;
ary = [["関東", "東京"],["関東","神奈川"],["関東","千葉"],["関東","埼玉"],["東海","愛知"],["東海","三重"],["東海","岐阜"],["北陸","富山"],["北陸","福井"],["北陸","石川"]];
ary4 = R.values(R.groupBy(R.head, ary));
console.log(ary4);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/27 22:16

    これすごいですね。Ramda恥ずかしながら初めて知りました。とっつきやすそうなライブラリで気に入りました。私はどうもライブラリが苦手なのですがこれは良さげです。有益な情報をありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる