配列に含まれる重複した要素を取得する

# やりたいこと

配列に含まれる重複した要素を取得したい。

```rb
animals = %w(🐶 🐱 🐰 🐱 🐵 🐰 🐰)
# animals.???
#=> ["🐱", "🐰"]
```

# 方法

## 1. [Enumerable#inject](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/inject.html) を使う

```rb
animals.each_with_index.inject([]) do |duplicated_animals, (animal, i)|
  # すでに重複していることが分かっている要素であればスキップする。
  next duplicated_animals if duplicated_animals.include?(animal)
  
  # animals の現在のインデックスより右側を調べる。
  duplicated_animals << animal if animals[i + 1..-1].include?(animal)
  duplicated_animals
end
#=> ["🐱", "🐰"]
```

## 2. [Enumerable#group_by](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/group_by.html) と [Object#itself](https://docs.ruby-lang.org/ja/latest/method/Object/i/itself.html) を使う

```rb
animals.group_by(&:itself).select { _2.size > 1 }.keys
#=> ["🐱", "🐰"]

# 解説
animals.group_by(&:itself)
#=> {"🐶"=>["🐶"], "🐱"=>["🐱", "🐱"], "🐰"=>["🐰", "🐰", "🐰"], "🐵"=>["🐵"]}
animals.group_by(&:itself).select { _2.size > 1 }
#=> {"🐱"=>["🐱", "🐱"], "🐰"=>["🐰", "🐰", "🐰"]}
animals.group_by(&:itself).select { _2.size > 1 }.keys
#=> ["🐱", "🐰"]
```

## 3. [Enumerable#count](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/count.html) を使う

```rb
animals.select { animals.count(_1) > 1 }.uniq
#=> ["🐱", "🐰"]
```

## 4. [Array#index](https://docs.ruby-lang.org/ja/latest/method/Array/i/find_index.html) と [Array#rindex](https://docs.ruby-lang.org/ja/latest/method/Array/i/rindex.html) を使う

```rb
# 右に向かって探索した場合と左に向かって探索した場合とで最初に見つかった位置が異なる場合、その要素が重複すると言える。
animals.select { animals.index(_1) != animals.rindex(_1) }.uniq
#=> ["🐱", "🐰"]
```

# パフォーマンス比較

```rb
# gem install benchmark-ips
require 'benchmark/ips'

numbers = Array.new(10_000) { [*1..100].sample }

Benchmark.ips do |x|
  x.report('1') do
    numbers.each_with_index.inject([]) do |duplicated_numbers, (number, i)|
      next duplicated_numbers if duplicated_numbers.include?(number)

      duplicated_numbers << number if numbers[i + 1..-1].include?(number)
      duplicated_numbers
    end
  end
  x.report('2') do
    numbers.group_by(&:itself).select { _2.size > 1 }.keys
  end
  x.report('3') do
    numbers.select { numbers.count(_1) > 1 }.uniq
  end
  x.report('4') do
    numbers.select { numbers.index(_1) != numbers.rindex(_1) }.uniq
  end
  x.compare!
end

# 念のためすべての方法の結果が等しいことを確認する。
results1 = numbers.each_with_index.inject([]) do |duplicated_numbers, (number, i)|
  next duplicated_numbers if duplicated_numbers.include?(number)

  duplicated_numbers << number if numbers[i + 1..-1].include?(number)
  duplicated_numbers
end
results2 = numbers.group_by(&:itself).select { _2.size > 1 }.keys
results3 = numbers.select { numbers.count(_1) > 1 }.uniq
results4 = numbers.select { numbers.index(_1) != numbers.rindex(_1) }.uniq

[results1, results2, results3, results4].uniq.size
#=> 1
```

```
Warming up --------------------------------------
                   1    38.000  i/100ms
                   2   202.000  i/100ms
                   3     1.000  i/100ms
                   4    12.000  i/100ms
Calculating -------------------------------------
                   1    385.300  (± 0.3%) i/s -      1.938k in   5.029877s
                   2      2.020k (± 1.2%) i/s -     10.100k in   5.001583s
                   3      2.627  (± 0.0%) i/s -     14.000  in   5.328698s
                   4    128.926  (± 0.0%) i/s -    648.000  in   5.026160s

Comparison:
                   2:     2019.6 i/s
                   1:      385.3 i/s - 5.24x  (± 0.00) slower
                   4:      128.9 i/s - 15.67x  (± 0.00) slower
                   3:        2.6 i/s - 768.72x  (± 0.00) slower
```

> 2\. [Enumerable#group_by](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/group_by.html) と [Object#itself](https://docs.ruby-lang.org/ja/latest/method/Object/i/itself.html) を使う

この方法が一番早い :rocket:

> 3\. [Enumerable#count](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/count.html) を使う

この方法が最も直感的だと僕は思うが、一番遅い :snail: