Rubyで配列内の重複する値を抽出する方法
こちらの記事の Rubyで配列から重複している値を抽出するのを考えてみた。
http://d.hatena.ne.jp/kiyo560808/20110801/1312196444
a = [1, 2, 3, 4, 5, 6, 5, 4] a.uniq.reject{|i| a.index(i) == a.rindex(i)} #=> [4, 5]
もしくは
a = [1, 2, 3, 4, 5, 6, 5, 4] a.uniq.reject{|i| a.count(i) == 1} #=> [4, 5]
こんな感じか?
ふとパフォーマンスが気になったので調べてみた。
#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'benchmark' a = (1..10000).to_a a += [1, 10000] Benchmark.bm do |x| x.report("Array#index:") do a.uniq.reject{|i| a.index(i) == a.rindex(i)} end x.report("Array#count:") do a.uniq.reject{|i| a.count(i) == 1} end x.report("using Hash:") do h = {} a.each do |i| h[i] ||= 0 h[i] += 1 end r = [] a.uniq.each do |i| r << i if h[i] > 1 end end end
user system total real Array#index: 12.430000 0.010000 12.440000 ( 12.461251) Array#count: 11.930000 0.000000 11.930000 ( 11.967026) using Hash: 0.020000 0.010000 0.030000 ( 0.029133)
結果、泥臭く書いたのがダントツで速いとか。
追記メモ
1行でやるなら
a.inject(Hash.new(0)){|h, i| h[i] += 1; h }.reject{|k, v| v <= 1 }.keys