Вспомогательный метод
Этот метод использует помощник:
class Array
def difference(other)
h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
reject { |e| h[e] > 0 && h[e] -= 1 }
end
end
Этот метод аналогичен Array#-. . Разница показана на следующем примере:
a = [3,1,2,3,4,3,2,2,4]
b = [2,3,4,4,3,4]
a - b #=> [1]
c = a.difference b #=> [1, 3, 2, 2]
Как видите, a
содержит три тройки, а b
содержит две, поэтому первые две тройки в a
удаляются при построении c
(a
не изменяется). Когда b
содержит столько же экземпляров элемента, сколько и a
, c
не содержит экземпляров этого элемента. Чтобы удалить элементы, начинающиеся с конца a
:
a.reverse.difference(b).reverse #=> [3, 1, 2, 2]
Array#difference!
можно определить очевидным образом.
Я предложил добавить этот метод в ядро Ruby.
При использовании с Array#-
этот метод упрощает извлечение уникальных элементов из массива a
:
Это работает, потому что
a = [1,3,2,4,3,4]
u = a.uniq #=> [1, 2, 3, 4]
u - a.difference(u) #=> [1, 2]
содержит все неуникальные элементы a
(каждый, возможно, более одного раза).
a.difference(u) #=> [3,4]
Проблема под рукой
Код
Примеры
class Array
def uniq_elements(&prc)
prc ||= ->(e) { e }
a = map { |e| prc[e] }
u = a.uniq
uniques = u - a.difference(u)
select { |e| uniques.include?(prc[e]) ? (uniques.delete(e); true) : false }
end
end
Вот еще один способ.
t = [1,2,2,3,4,4,5,6,7,7,8,9,9,9]
t.uniq_elements
#=> [1,3,5,6,8]
t = [1.0, 1.1, 2.0, 3.0, 3.4, 4.0, 4.2, 5.1, 5.7, 6.1, 6.2]
t.uniq_elements { |z| z.round }
# => [2.0, 5.1]
person
Cary Swoveland
schedule
28.07.2014