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

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

ただいまの
回答率

89.64%

2つの配列を同時にeach - 2つの配列を統合して並び替え

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,287

michopp

score 5

@prefecture_array = [ id: 1, name: "北海道"], [ id: 5, name: "東京"]

@city_array = [id: 35, prefecture_id: 2, name: "札幌"], [ id: 49, prefecture_id: 10, name: "浜松"], [ id: 51, prefecture_id: 15, name: "神戸"]

上記の配列があり、
@prefecture_arrayのidと、@city_arrayのprefecture_idを調べて、1~順にソートしたいのですが、(この場合は北海道、札幌、東京、浜松、神戸の順に)下記の方法で試していますが、上手くソートができません。

どなたか方法が分かります方、お教え頂けませんでしょうか?

    all_array = []
    @prefecture_array.each do |prefecture|
      @area_group_array.each do |area_group|
        if prefecture.id <= area_group.prefecture_id
          all_array << prefecture
        elsif area_group.prefecture_id < prefecture.id
          all_array << area_group
        end 
      end
    @all_array = all_array
    end

また、

    all_array = []
      @prefecture_array.zip(@area_group_array).each do |prefecture, area_group|
        if prefecture.id <= area_group.prefecture_id
          all_array << prefecture
        elsif area_group.prefecture_id < prefecture.id
          all_array << area_group
        end
      end
    @array = all_array
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • gouf

    2017/04/24 19:32

    仮にこれを実現したとして、実際にやりたいことはなんですか(より簡単な方法が見つかるかもしれません)

    キャンセル

  • michopp

    2017/04/25 10:45

    有難うございます。選択したPrefecturesとCitiesをviewで表示させる時に、別々に表示をするのではなく、例えば北海道と札幌が選択されていたとすると、北海道・札幌の順に並び替えたいです。同じエリアという枠の中で表示したいので、都道府県でも都市名であっても、別々ではなく、同じ認識として表示させたいというのが主旨になります。

    キャンセル

回答 2

checkベストアンサー

+1

all_arr = []
prefecture_arr = [{id: 1,name:"北海道"},{id: 5,name: "東京"}]
city_arr = [{id: 35, prefecture_id: 2, name: "札幌"},{id: 49, prefecture_id: 10, name: "浜松"}]
all_arr.push(prefecture_arr, city_arr)

def has_prefecture?(arr)
  Hash[arr].has_key?(:prefecture_id)
end

all_arr = all_arr.flatten.map(&:to_a).sort{ |a, b|
  #p b
  if has_prefecture?(a) && has_prefecture?(b)
    a[1][1] <=> b[1][1]
  elsif has_prefecture?(a)
    a[1][1] <=> b[0][1]
  elsif has_prefecture?(b)
    a[0][1] <=> b[1][1]
  else
    a[0][1] <=> b[0][1]
  end
}.map{|s| Hash[s]}
p all_arr
[{:id=>1, :name=>"北海道"}, {:id=>35, :prefecture_id=>2, :name=>"札幌"}, {:id=>5, :name=>"東京"}, {:id=>49, :prefecture_id=>10, :name=>"浜松"}]

cityのidを残した場合でのコードを書いてみました。
同時にいくつかのカラムを持つそうですが、現状どのようなものがあり、どの順番で格納されているかわからないため、sortの際のaとbの要素の取り出しは上記のようになっています
rails consoleで格納されている順番を確認したのち、それに対応したコードに変更してみてください

考え方としてはsortは二つの要素を比較して順番を入れ替えるメソッドなのでa,bの両方をhas_prefecture?メソッドでそれぞれの配列をhash化した後にprefecture_idのキーを持っているか判定
両方ともprefecture_idを持っていたらそれで比較
片方しかなかったらその片方をprefecture_idの持つバリュー、もう片方をidの持つバリューで比較
両方ともprefecture_idを持っていなかったらidで比較となっております
sortをする際にto_aでそれぞれの要素を配列化してしまったのでhash化してあげて終わりです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/04/27 15:56

    こちらのご回答を実際の配列で試して、上手くいきました!
    大変ご丁寧な解説、感謝いたします!

    キャンセル

+1

@city_arrayのidは必要ないものと考えてもよろしいでしょうか?
それでしたらこちらのコードでどうでしょう

all_arr = []
prefecture_arr = [{id: 1,name:"北海道"},{id: 5,name: "東京"}]
#p prefecture_arr

city_arr = [{id: 35, prefecture_id: 2, name: "札幌"},{id: 49, prefecture_id: 10, name: "浜松"}]
city_arr.map{|s| s.delete(:id)}#.tap{|s| p s }
all_arr.push(prefecture_arr, city_arr)

p all_arr.flatten.map(&:to_a).sort{|a, b| a[0][1] <=> b[0][1] }
[[[:id, 1], [:name, "北海道"]], [[:prefecture_id, 2], [:name, "札幌"]], [[:id, 5], [:name, "東京"]], [[:prefecture_id, 10], [:name, "浜松"]]]


軽く解説すると

  1. 空の配列を用意
  2. city_arrのハッシュの:idの部分を削除する
  3. 空の配列にprefecture_arrayとcity_arrをpushで加える
  4. flattenで配列を平坦化したのちに全てのhashをto_aで配列化、その後sortでそれぞれの配列のid,もしくはprefecture_idの要素の値で並び替える

これで一応並び順を変えることが出来ました
@cityのidが必要でしたらまた考えてみます

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/04/25 20:14

    haneru様、どうも有難うございます。
    説明不足でしたが、実際のprefectureとcityはDBのテーブルから取得したものからか、cityの:idを削除する部分で上手く行きませんでした。
    また、並び替えた要素を表示する際に、同時にいくつかのカラムの要素も持って来るため、できましたらcityもidを残しておきたいです。

    こちらのご紹介いただいた方法も今後大変参考になると思いますので、感謝いたします!

    キャンセル

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

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