3

suppose I have an array [1,2,3,1,5,2]. Here 1 and 2 are the repeated elements. I want to get a new array [1,2].

How do I do that in ruby ??

Prabesh Shrestha
  • 2,732
  • 4
  • 29
  • 44

2 Answers2

12
arr = [1,2,3,1,5,2]
arr.group_by {|e| e}.map { |e| e[0] if e[1][1]}.compact

Pretty ugly... but does the job without an n+1 problem.

Pavling
  • 3,933
  • 1
  • 22
  • 25
  • 4
    Also, perhaps clearer `arr.group_by { |v| v }.select { |k, v| v.count > 1 }.keys` – d11wtq Dec 10 '11 at 22:42
  • 1
    I actually started with that exact line, but took the .count out to do one less operation for every element. – Pavling Dec 11 '11 at 12:01
4
arr = [1,2,3,1,5,2]
arr.select { |x| arr.count(x) > 1 } .uniq

A longer solution using reduce should be quicker.

arr.reduce [{}, []] do |(seen, out), cur|
  case seen[cur]
    when :seen then
      [seen.merge({cur => :added}), out << cur]
    when :added then
      [seen, out]
    else
     [seen.merge({cur => :seen}), out]
  end
end.last
Jan
  • 11,636
  • 38
  • 47
  • I wrote something similar in the duplicated question: http://stackoverflow.com/a/8459032/188031. But I see some problems here: 1) you are using an array object to test inclussion, which is O(n), a hash or set would be more suitable. 2) you can safely remove the `uniq`. 3) Use arguments expansion instead of acc[0]/acc[1]. – tokland Dec 10 '11 at 19:02
  • @tokland, thanks for the comment. 1) I've switched to `Hash`. 2) No, unfortunately not. See `[1,1,1]`. 3) Good point! – Jan Dec 10 '11 at 19:20
  • After the last change `uniq` isn't necessary any longer. – Jan Dec 10 '11 at 19:39
  • 1
    you are right! now I have to check my solution. – tokland Dec 10 '11 at 19:49