- Rubyで重複する値を排除したい場合は、uniqメソッドを使えばOK。
a = [1, 2, 3, 4, 5, 6, 5, 4] a.uniq #=> [1, 2, 3, 4, 5, 6]
- 重複している値があるかどうかを調べるなら、uniqを利用すれば簡単にわかる。
a = [1, 2, 3, 4, 5, 6, 5, 4] a.size == a.uniq.size #=> false
でも、配列から重複している値を抽出するメソッドは見当たらない(たぶん)。
そこで、配列から重複している値を抽出するスクリプトを書いてみた。
- 配列から重複している値を抽出する
a = [1, 2, 3, 4, 5, 6, 5, 4] a.uniq.map{|v| v if a.inject(Hash.new(0)) {|h, key| h[key] += 1; h}[v] >= 2}.compact #=> [4, 5]
-
- やっていることは、
- 配列aの値をキーとしてハッシュを作り、出現した回数をカウントする ⇒ a.inject(Hash.new(0)) {|h, key| h[key] += 1; h}
- バリューが2以上の場合、キーを返す。 ⇒ v if a.inject(Hash.new(0)) {|h, key| h[key] += 1; h}[v] >= 2
- 配列aが持つユニークな値それぞれについて上記を繰り返す。 ⇒ a.uniq.map{|v| v if a.inject(Hash.new(0)) {|h, key| h[key] += 1; h}[v] >= 2}
- nilの値を排除する。 ⇒ a.uniq.map{|v| v if a.inject(Hash.new(0)) {|h, key| h[key] += 1; h}[v] >= 2}.compact
- ちょっと入り組んでいるが、1行でさくっと、もれなく抽出できる。
- ちなみに、2を3にすると3つ以上あるものを抽出できたりする。
- メソッドとして定義しておくと便利かも。
- やっていることは、
しかし、このコードには大きな問題があった。
これだとn+1問題的な問題が発生し、パフォーマンスが著しく悪い。a.inject・・・が毎回行われてしまっている。
そこで、メソッドを以下のように修正。
a = [1, 2, 3, 4, 5, 6, 5, 4] a.inject(Hash.new(0)){|h, key| h[key] += 1; h}.map {|k,v| k if v >= 2}.compact #=> [4, 5]
- @yohfeeさんから紹介して頂いた下記のやり方もシンプルで良いと思う。
- ただし、ruby1.8.7以上に限る。1.8.6だとone?メソッドがないので、v.size == 1に書き換える必要がある。
a = [1, 2, 3, 4, 5, 6, 5, 4] a.group_by{|i| i}.reject{|k,v| v.one?}.keys #=> [4, 5]
- パフォーマンスチェック
require 'benchmark' a = (1..5000).to_a a += [1,3,4,5,2000,4,2] Benchmark.bm do |x| x.report("hash_before:") do a.uniq.map{|v| (a.inject(Hash.new(0)) {|h, key| h[key] += 1; h}[v] >= 2) ? v : nil}.compact end x.report("hash_after :") do a.inject(Hash.new(0)){|h, key| h[key] += 1; h}.map {|k,v| k if v >= 2}.compact end x.report("use_group_by:") do a.group_by{|i| i}.reject{|k,v| v.one?}.keys end end # user system total real # hash_before: 99.370000 25.070000 124.440000 (200.303787) # hash_after : 0.020000 0.010000 0.030000 ( 0.038642) # use_group_by: 0.040000 0.010000 0.050000 ( 0.052790)
-
- 最初に作ったものに比べて、パフォーマンスが5000倍くらい改善
- group_byを使ったやり方も、パフォーマンスはほとんど遜色ない。
※injectメソッドは目新しいかもしれないけど、ここのサイトを見るとよくわかる。
Rubyのオススメ書籍
- 作者: 久保秋真
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2013/11/21
- メディア: Kindle版
- この商品を含むブログ (3件) を見る
言語を学ぶのは文法から入るより実践から入ったほうがよいというのがよくわかる。
- 作者: Yugui
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/06/26
- メディア: 大型本
- 購入: 27人 クリック: 644回
- この商品を含むブログ (253件) を見る
Rubyのポイントがシンプルにまとめられていて、Rubyへの理解が深まる。
お読み頂きありがとうございます。
もしブログの内容を気に入って頂けましたら、RSSリーダーの登録よろしくお願いします。
twitter@kbktもやってます。IT系の最新情報やライフハック情報をよくつぶやいています。よろしければフォローしてください。
◆◆このブログのサイトマップへ◆◆
最近書いたまとめ記事
最近、Naverまとめを利用し、役に立った記事を集約し、内容をまとめています。よろしければご覧ください。参考になれば幸いです。
- Rubyを基礎からしっかり学習できるサイトまとめ - NAVER まとめ
- 優れたwebデザインの考え方、つくり方、学び方と参考になるサイト - NAVER まとめ
- プレゼンのコツ、技術、トレーニング方法まとめ【知らないと損をするプレゼンの基礎知識】 - NAVER まとめ
- 自分のプログラミングレベルを知ることができるサイトまとめ - NAVER まとめ
- 残業を減らす方法まとめ - NAVER まとめ
- 【オススメ】初めてAndroidを使う人が見ると良いアプリサイト一覧 - NAVER まとめ
- 高速でプログラミング言語をマスターするのに有効な記事まとめ - NAVER まとめ
- Macを買ったら読んでおかないと損をすると思うサイト まとめ - NAVER まとめ
- 【マインドマップの基礎知識】マインドマップの書き方がマスターできる方法まとめ - NAVER まとめ