[英]How to count duplicates in Ruby Arrays
你如何計算 ruby 數組中的重復項?
例如,如果我的數組有三個 a,我怎么算
散列的另一個版本,其中包含數組中每個元素的鍵和每個元素計數的值
a = [ 1, 2, 3, 3, 4, 3]
h = Hash.new(0)
a.each { | v | h.store(v, h[v]+1) }
# h = { 3=>3, 2=>1, 1=>1, 4=>1 }
鑒於:
arr = [ 1, 2, 3, 2, 4, 5, 3]
我最喜歡的元素計數方法是:
counts = arr.group_by{|i| i}.map{|k,v| [k, v.count] }
# => [[1, 1], [2, 2], [3, 2], [4, 1], [5, 1]]
如果您需要散列而不是數組:
Hash[*counts.flatten]
# => {1=>1, 2=>2, 3=>2, 4=>1, 5=>1}
這將產生重復元素作為散列,每個重復項的出現次數。 讓代碼說話:
#!/usr/bin/env ruby
class Array
# monkey-patched version
def dup_hash
inject(Hash.new(0)) { |h,e| h[e] += 1; h }.select {
|k,v| v > 1 }.inject({}) { |r, e| r[e.first] = e.last; r }
end
end
# unmonkeey'd
def dup_hash(ary)
ary.inject(Hash.new(0)) { |h,e| h[e] += 1; h }.select {
|_k,v| v > 1 }.inject({}) { |r, e| r[e.first] = e.last; r }
end
p dup_hash([1, 2, "a", "a", 4, "a", 2, 1])
# {"a"=>3, 1=>2, 2=>2}
p [1, 2, "Thanks", "You're welcome", "Thanks",
"You're welcome", "Thanks", "You're welcome"].dup_hash
# {"You're welcome"=>3, "Thanks"=>3}
簡單的。
arr = [2,3,4,3,2,67,2]
repeats = arr.length - arr.uniq.length
puts repeats
arr = %w( a b c d c b a )
# => ["a", "b", "c", "d", "c", "b", "a"]
arr.count('a')
# => 2
計算數組重復的另一種方法是:
arr= [2,2,3,3,2,4,2]
arr.group_by{|x| x}.map{|k,v| [k,v.count] }
結果是
[[2, 4], [3, 2], [4, 1]]
group_by
需要 1.8.7+
ary = %w{a b c d a e f g a h i b}
ary.group_by{|elem| elem}.select{|key,val| val.length > 1}.map{|key,val| key}
# => ["a", "b"]
使用 1.9+ 這可以稍微簡化,因為 Hash#select 將返回一個散列。
ary.group_by{|elem| elem}.select{|key,val| val.length > 1}.keys
# => ["a", "b"]
要計算單個元素的實例,請使用注入
array.inject(0){|count,elem| elem == value ? count+1 : count}
arr = [1, 2, "a", "a", 4, "a", 2, 1]
arr.group_by(&:itself).transform_values(&:size)
#=> {1=>2, 2=>2, "a"=>3, 4=>1}
grep 呢?
arr = [1, 2, "Thanks", "You're welcome", "Thanks", "You're welcome", "Thanks", "You're welcome"]
arr.grep('Thanks').size # => 3
我認為沒有內置方法。 如果你需要的只是重復的總數,你可以取 a.length - a.uniq.length。 如果您正在尋找單個特定元素的計數,請嘗試a.select {|e| e == my_element}.length
a.select {|e| e == my_element}.length
。
它很簡單:
words = ["aa","bb","cc","bb","bb","cc"]
一行簡單的解決方案是:
words.each_with_object(Hash.new(0)) { |word,counts| counts[word] += 1 }
這個對我有用。
謝謝!!
改進@Kim 的回答:
arr = [1, 2, "a", "a", 4, "a", 2, 1]
Hash.new(0).tap { |h| arr.each { |v| h[v] += 1 } }
# => {1=>2, 2=>2, "a"=>3, 4=>1}
獲取數組中重復元素的Ruby代碼:
numbers = [1,2,3,1,2,0,8,9,0,1,2,3]
similar = numbers.each_with_object([]) do |n, dups|
dups << n if seen.include?(n)
seen << n
end
print "similar --> ", similar
另一種方法是使用each_with_object
:
a = [ 1, 2, 3, 3, 4, 3]
hash = a.each_with_object({}) {|v, h|
h[v] ||= 0
h[v] += 1
}
# hash = { 3=>3, 2=>1, 1=>1, 4=>1 }
這樣,在Kim 的解決方案中,調用不存在的鍵(例如hash[5]
將返回nil
而不是0
。
我過去曾為此使用過reduce
/ inject
,如下所示
array = [1,5,4,3,1,5,6,8,8,8,9]
array.reduce (Hash.new(0)) {|counts, el| counts[el]+=1; counts}
產生
=> {1=>2, 5=>2, 4=>1, 3=>1, 6=>1, 8=>3, 9=>1}
Ruby >= 2.7解決方案在這里:
添加了一個新方法.tally
。
統計集合,即計算每個元素的出現次數。 返回一個散列,其中集合的元素作為鍵,相應的計數作為值。
所以現在,你將能夠做到:
["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.