LoginSignup
1
2

More than 5 years have passed since last update.

Rails API Sort

Last updated at Posted at 2018-09-07

APIデータより抽出したデータを、要素を指定してsort

#変数.sort_by { |変数| (-なら降順)変数['任意の要素'].to_i }
@results.sort_by! { |hash| hash['releaseDate'].to_i }

このように記述することで、指定した要素よりsort機能を利用することができる。

修正!!

上記コードでは抽出したデータ(2017-07-20)を年ではソート出来ているものの、月日まではソート出来ていないケースが非常に多かったことを見逃していたため、修正した形が以下のコードになります。
Rubyにおける通常のソートと見た目はあまり変わりません。
ただArrayではなくHashのsortになるので、a['key']とする必要あり。

@results.sort! {|a, b| a['releaseDate'] <=> b['releaseDate'] }

以下解決に到るまでの道程

APIより抽出したjson配列をそのまま変数に格納。
以下はiTunesの例。

url = "https://itunes.apple.com/search?term=井上陽水&lang=ja_jp&country=JP&media=music&limit=100"
    uri = URI.encode(url)
    info = URI.parse(uri)
    json = Net::HTTP.get(info)
    result = JSON.parse(json)
    @results = result["results"]

ここで@resultsのクラスを確認することで適用できるメソッドを探る。

@results.class
=>Array

配列と出てきたが、実際に入っているデータ構造はhashである為

> {"wrapperType"=>"track", "kind"=>"song", "artistId"=>76112633, "collectionId"=>284457303, "trackId"=>284457304, "artistName"=>"井上陽水", "collectionName"=>"少年時代 - Single", "trackName"=>"少年時代", "collectionCensoredName"=>"少年時代 - Single", "trackCensoredName"=>"少年時代", "artistViewUrl"=>"https://itunes.apple.com/jp/artist/%E4%BA%95%E4%B8%8A%E9%99%BD%E6%B0%B4/76112633?uo=4", "collectionViewUrl"=>"https://itunes.apple.com/jp/album/%E5%B0%91%E5%B9%B4%E6%99%82%E4%BB%A3/284457303?i=284457304&uo=4", "trackViewUrl"=>"https://itunes.apple.com/jp/album/%E5%B0%91%E5%B9%B4%E6%99%82%E4%BB%A3/284457303?i=284457304&uo=4", "previewUrl"=>"https://audio-ssl.itunes.apple.com/apple-assets-us-std-000001/AudioPreview62/v4/cc/d0/d2/ccd0d255-51e5-608c-1f30-a33da272aaf9/mzaf_103202930428167730.plus.aac.p.m4a", "artworkUrl30"=>"https://is2-ssl.mzstatic.com/image/thumb/Music/v4/57/97/ff/5797ff38-0680-cd6b-7a0d-29cbc34cf368/source/30x30bb.jpg", "artworkUrl60"=>"https://is2-ssl.mzstatic.com/image/thumb/Music/v4/57/97/ff/5797ff38-0680-cd6b-7a0d-29cbc34cf368/source/60x60bb.jpg", "artworkUrl100"=>"https://is2-ssl.mzstatic.com/image/thumb/Music/v4/57/97/ff/5797ff38-0680-cd6b-7a0d-29cbc34cf368/source/100x100bb.jpg", "collectionPrice"=>500.0, "trackPrice"=>250.0, "releaseDate"=>"1990-09-21T07:00:00Z", "collectionExplicitness"=>"notExplicit", "trackExplicitness"=>"notExplicit", "discCount"=>1, "discNumber"=>1, "trackCount"=>2, "trackNumber"=>1, "trackTimeMillis"=>201027, "country"=>"JPN", "currency"=>"JPY", "primaryGenreName"=>"J-Pop", "isStreamable"=>false}

keyとそれに対応するvaluesより出来ているhashである。
そこで配列のfirstメソッドを用いて最初の要素を抽出してclassを確認すると

@results.first.class
=>Hash

やはりデータが格納されているのはHashクラスである。
Hashであるならばkeyを指定することで要素が取り出せるはずなので

@results.first("releaseDate")
TypeError: no implicit conversion of String into Integer

要素を取り出そうとすると数値に変換出来ないとのエラーが生じる。
これは以前teratailにて質問した際に頂いた回答

@members[:name]
TypeError: no implicit conversion of Symbol into Integer

Array#[]がdelegateでrecordsを通して呼ばれています。
@members.records[:name]と同義です。
Array#[]は引数を暗黙的に数値変換します(to_intという厳密な変換です)。
:nameはto_intできる対象ではないため、このエラーが発生したのだと思います。

よりhashに対応するメソッドをarrayクラスに用いていたこととなる。

そこでhashとなるfirstを付与した後にvalues_atを用いることでデータの抽出に成功。

@results.first.values_at("releaseDate")
=>["1990-09-21T07:00:00Z"]

再び問題となるのが、これをどう利用してsortに結びつけるか。

@results.sory_by(@results.values_at("releaseDate"))
=>TypeError: no implicit conversion of String into Integer

sort_byメソッドの引数に先ほど得ることの出来たメソッドをそのまま代入してみるもエラー。
それもそのはず今回はfirstが付いていない為にhashに用いていたvalues_atが使えないことになるから・・?

最終的に参考となったサイトがこちら
SONな配列を、指定の項目でソートをかける、PHPとRuby比較

またteratailより頂いたpluckメソッドを使用すると

@results.pluck("releaseDate")
=> ["1990-09-21T07:00:00Z", "2017-05-31T07:00:00Z", "1993-07-21T07:00:00Z", "2018-06-08T07:00:00Z", "1984-12-21T08:00:00Z", "2014-12-09T08:00:00Z", "2018-05-23T07:00:00Z", "2017-01-20T08:00:00Z", "2008-07-16T07:00:00Z", "2008-12-10T08:00:00Z", "1984-12-21T08:00:00Z", "1984-12-21T08:00:00Z", "1982-12-05T08:00:00Z", "2008-12-10T08:00:00Z", "2008-07-16T07:00:00Z", "2008-07-16T07:00:00Z", "2008-07-16T07:00:00Z", "2008-12-10T08:00:00Z", "1980-12-05T08:00:00Z", "1984-12-21T08:00:00Z", "2008-12-10T08:00:00Z", "2008-12-10T08:00:00Z", "1986-01-01T08:00:00Z", "1984-12-21T08:00:00Z", "2008-07-16T07:00:00Z", "1990-10-21T07:00:00Z", "2008-07-16T07:00:00Z", "2010-11-17T08:00:00Z", "1987-12-16T08:00:00Z", "1990-10-21T07:00:00Z", "2008-07-16T07:00:00Z", "2008-07-16T07:00:00Z", "1973-12-01T08:00:00Z", "2008-07-16T07:00:00Z", "2008-07-16T07:00:00Z", "1981-11-21T08:00:00Z", "2008-12-10T08:00:00Z", "2010-11-17T08:00:00Z", "1992-11-20T08:00:00Z", "2008-12-10T08:00:00Z", "1976-03-25T08:00:00Z", "1984-12-21T08:00:00Z", "2008-07-16T07:00:00Z", "2008-12-10T08:00:00Z", "2008-07-16T07:00:00Z", "1982-12-05T08:00:00Z", "2008-12-10T08:00:00Z", "2008-07-16T07:00:00Z", "2008-12-10T08:00:00Z", "1976-03-25T08:00:00Z", "2008-07-16T07:00:00Z", "1973-12-01T08:00:00Z", "1990-10-21T07:00:00Z", "2009-04-29T07:00:00Z", "2008-12-10T08:00:00Z", "2001-05-30T07:00:00Z", "2008-12-10T08:00:00Z", "2008-12-10T08:00:00Z", "1984-12-21T08:00:00Z", "1973-12-01T08:00:00Z", "1990-09-21T07:00:00Z", "2008-07-16T07:00:00Z", "2008-12-10T08:00:00Z", "1984-12-21T08:00:00Z", "2002-07-24T07:00:00Z", "1982-12-05T08:00:00Z", "1976-03-25T08:00:00Z", "1984-12-21T08:00:00Z", "1986-01-01T08:00:00Z", "1976-03-25T08:00:00Z", "1979-09-21T07:00:00Z", "1973-12-01T08:00:00Z", "1973-12-01T08:00:00Z", "1992-11-20T08:00:00Z", "1976-03-25T08:00:00Z", "1986-01-01T08:00:00Z", "1982-12-05T08:00:00Z", "1993-09-15T07:00:00Z", "1973-12-01T08:00:00Z", "1979-09-21T07:00:00Z", "1973-12-01T08:00:00Z", "1976-03-25T08:00:00Z", "1976-03-25T08:00:00Z", "1979-09-21T07:00:00Z", "1982-12-05T08:00:00Z", "1973-12-01T08:00:00Z", "1976-03-25T08:00:00Z", "1973-12-01T08:00:00Z", "1982-12-05T08:00:00Z", "1986-01-01T08:00:00Z", "1990-10-21T07:00:00Z", "2010-11-17T08:00:00Z", "1990-10-21T07:00:00Z", "1982-12-05T08:00:00Z", "1976-03-25T08:00:00Z", "1992-11-20T08:00:00Z", "1986-01-01T08:00:00Z", "1990-10-21T07:00:00Z", "1992-11-20T08:00:00Z", "1992-11-20T08:00:00Z"]

該当要素一覧を取得することが出来、またsortを繋げることもできる。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2