Cómo encontrar y devolver un valor duplicado en una matriz

Resuelto Misha Moroshko asked hace 12 años • 23 respuestas

arres una matriz de cadenas:

["hello", "world", "stack", "overflow", "hello", "again"]

¿Cuál sería una forma fácil y elegante de comprobar si arrhay duplicados y, de ser así, devolver uno de ellos (sin importar cuál)?

Ejemplos:

["A", "B", "C", "B", "A"]    # => "A" or "B"
["A", "B", "C"]              # => nil
Misha Moroshko avatar Jan 19 '12 13:01 Misha Moroshko
Aceptado
a = ["A", "B", "C", "B", "A"]
a.detect{ |e| a.count(e) > 1 }

Sé que esta no es una respuesta muy elegante, pero me encanta. Es un hermoso código de una sola línea. Y funciona perfectamente bien a menos que necesite procesar un gran conjunto de datos.

¿Busca una solución más rápida? ¡Aquí tienes!

def find_one_using_hash_map(array)
  map = {}
  dup = nil
  array.each do |v|
    map[v] = (map[v] || 0 ) + 1

    if map[v] > 1
      dup = v
      break
    end
  end

  return dup
end

Es lineal, O(n), pero ahora necesita administrar múltiples líneas de código, necesita casos de prueba, etc.

Si necesita una solución aún más rápida, tal vez pruebe con C.

Y aquí está la esencia comparando diferentes soluciones: https://gist.github.com/naveed-ahmad/8f0b926ffccf5fbd206a1cc58ce9743e

Naveed avatar Jan 19 '2012 08:01 Naveed

Puedes hacer esto de varias maneras, siendo la primera opción la más rápida:

ary = ["A", "B", "C", "B", "A"]

ary.group_by{ |e| e }.select { |k, v| v.size > 1 }.map(&:first)

ary.sort.chunk{ |e| e }.select { |e, chunk| chunk.size > 1 }.map(&:first)

Y una opción O(N^2) (es decir, menos eficiente):

ary.select{ |e| ary.count(e) > 1 }.uniq
Ryan LeCompte avatar Jan 19 '2012 06:01 Ryan LeCompte