Возвращение похожих элементов массива в Ruby
Скажем, у меня такой массив:
arr = ['footballs_jumba_10', 'footballs_jumba_11', 'footballs_jumba_12',
'footballs_jumba_14', 'alpha_romeo_11', 'alpha_romeo_12',
'alpha_juliet_10', 'alpha_juliet_11']
Если бы я хотел вернуть дубликаты (если любая из этих строк в массиве была абсолютно одинаковой, я бы просто
return arr.detect{ |a| arr.count(a) > 1 }
но что, если бы я хотел получить только дубликаты первых 10 символов каждого элемента массива, не зная об изменениях заранее? Вот так:
['footballs_', 'alpha_rome', 'alpha_juli']
Ответы
Ответ 1
Это довольно просто с методом Arry#difference
, который я предложил в своем ответе здесь:
arr << "Let add a string that appears just once"
#=> ["footballs_jumba_10", "footballs_jumba_11", "footballs_jumba_12",
# "footballs_jumba_14", "alpha_romeo_11", "alpha_romeo_12",
# "alpha_juliet_10", "alpha_juliet_11", "Let add a string that appears just once"]
a = arr.map { |s| s[0,10] }
#=> ["footballs_", "footballs_", "footballs_", "footballs_", "alpha_rome",
# "alpha_rome", "alpha_juli", "alpha_juli", "Let add "]
b = a.difference(a.uniq)
#=> ["footballs_", "footballs_", "footballs_", "alpha_rome", "alpha_juli"]
b.uniq
#=> ["footballs_", "alpha_rome", "alpha_juli"]
Ответ 2
Используйте Array#uniq
:
arr.map {|e| e[0..9]}.uniq
# => ["footballs_", "alpha_rome", "alpha_juli"]
Ответ 3
Вы можете сделать что-то вроде этого:
def partial_duplicates(elements)
unique = {}
duplicates = {}
elements.each do |e|
partial = e[0..9]
# If the element is in the hash, it is a duplicate.
if first_element = unique[partial]
duplicates[first_element] = true
duplicates[e] = true
else
# include the element as unique
unique[partial] = e
end
end
duplicates.keys
end
Это приведет к возврату уникальных дубликатов. Если вы хотите все дубликаты, вы можете просто использовать Array
.
Кроме того, это возвращает все полные представления каждого дубликата, поскольку он кажется более полезным и, вероятно, тем, что вы хотите:
partial_duplicates(arr)
=> ["footballs_jumba_10", "footballs_jumba_11", "footballs_jumba_12", "footballs_jumba_14", "alpha_romeo_11", "alpha_romeo_12", "alpha_juliet_10", "alpha_juliet_11"]
Если вы хотите только частичные дубликаты, вы можете изменить условие:
if unique[partial]
duplicates[partial] = true
else
unique[partial] = true
end
то
partial_duplicates(arr)
=> ["footballs_", "alpha_rome", "alpha_juli"]