2010-12-04 3 views
60

У меня есть массив А. Я бы хотел проверить, содержит ли он повторяющиеся значения. Как мне это сделать?Как проверить массив для дубликатов?

+14

«помечены как дубликат» хорошо это довольно мета рассмотрении вопроса. – cpursley

+1

«Как проверить массив для дубликатов?» не совсем такой же вопрос, как «Как найти и вернуть дублирующее значение в массив?». Этот вопрос задает вопрос о том, как определить уникальность массива, тогда как другой задает вопрос о том, как вытаскивать повторяющиеся значения из массива. Я не думаю, что это должно быть отмечено как дубликат, но другой вопрос аналогичен и должен быть связан в комментарии. – emery

+0

Но ирония богата, не так ли? – oMiKeY

ответ

114

Просто позвоните uniq на нем (который возвращает новый массив без дубликатов), и имеет ли массив uniq-е изд меньше элементов, чем оригинал:

if a.uniq.length == a.length 
    puts "a does not contain duplicates" 
else 
    puts "a does contain duplicates" 
end 

Обратите внимание, что объекты в массиве должны реагировать на hash и eql? в значении для uniq для правильной работы.

+8

Кроме того, 'uniq!' Будет возвращать 'nil', если не будет найдено дубликатов, изменяя self для удаления дубликатов. Существует множество методов массивов: http://ruby-doc.org/core/classes/Array.html – David

+2

Конечно, если они не отвечают на 'eql?' Значимым образом, то что делает " дублировать "даже ** означает **? И как только вы определили 'eql?', 'Hash' должен быть совместим с ним. –

+1

@Karl: Эти два элемента в массиве '==' друг к другу? – sepp2k

32

Чтобы найти дублированные элементы, я использую этот подход (с Руби 1.9.3):

array = [1, 2, 1, 3, 5, 4, 5, 5] 
=> [1, 2, 1, 3, 5, 4, 5, 5] 
dup = array.select{|element| array.count(element) > 1 } 
=> [1, 1, 5, 5, 5] 
dup.uniq 
=> [1, 5] 
+3

select {array.count} - это вложенный цикл, вы выполняете комплексный алгоритм O (n^2) для чего-то, что можно сделать в O (n). – apeiros

+1

Вы правы, чтобы решить этот вопрос Скицита, который мы можем использовать в O (n); но для того, чтобы выяснить, какие элементы дублируются, O (n^2) algo - единственный способ, о котором я могу думать до сих пор. – jmonteiro

+3

сортировать и удалять цепочки для n log n – user3125280

4

Может хотите monkeypatch массив, если использовать это больше, чем один раз:

class Array 
    def uniq? 
    self.length == self.uniq.length 
    end 
end 

Тогда:

irb(main):018:0> [1,2].uniq? 
=> true 
irb(main):019:0> [2,2].uniq? 
=> false 
+14

Я бы избегал патчей обезьян, чтобы обернуть однострочный. –

+0

обезьяньи патчи имеют тенденцию укусить –

+0

@sidewaysmilk почему этого следует избегать? Это похоже на рубиновый путь: элегантный, динамичный и сухой. – hamstar

9

Если вы хотите возвратить дубликаты, вы можете сделать это:

dups = [1,1,1,2,2,3].group_by{|e| e}.keep_if{|_, e| e.length > 1} 
# => {1=>[1, 1, 1], 2=>[2, 2]} 

Если вы хотите только значения:

dups.keys 
# => [1, 2] 

Если вы хотите, количество дублей:

dups.map{|k, v| {k => v.length}} 
# => [{1=>3}, {2=>2}] 
Смежные вопросы