arr = [1,2,1,3,5,2,4]
Run Code Online (Sandbox Code Playgroud)
如何通过排序按组值计算数组?我需要以下输出:
x[1] = 2
x[2] = 2
x[3] = 1
x[4] = 1
x[5] = 1
Run Code Online (Sandbox Code Playgroud)
Mic*_*ohl 106
x = arr.inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
Run Code Online (Sandbox Code Playgroud)
saw*_*awa 32
仅适用于红宝石1.9
基本上与迈克尔的答案相同,但稍微短一些:
x = arr.each_with_object(Hash.new(0)) {|e, h| h[e] += 1}
Run Code Online (Sandbox Code Playgroud)
在类似的情况下,
Array
,, Hash
)时String
,可以使用each_with_object
,如上例所示.当起始元素是一个不可变对象时Numeric
,你必须使用inject
如下.
sum = (1..10).inject(0) {|sum, n| sum + n} # => 55
lll*_*lll 15
另一个 - 与其他人类似 - 接近:
result=Hash[arr.group_by{|x|x}.map{|k,v| [k,v.size]}]
Run Code Online (Sandbox Code Playgroud)
result[1]=2 ...
.Eli*_*adL 13
arr.group_by(&:itself).transform_values(&:size)
#=> {1=>2, 2=>2, 3=>1, 5=>1, 4=>1}
Run Code Online (Sandbox Code Playgroud)
rub*_*nce 10
x = Hash[arr.uniq.map{ |i| [i, arr.count(i)] }]
Run Code Online (Sandbox Code Playgroud)
Mr.*_*ack 10
中有一个简短的版本ruby 2.7 => Enumerable#tally
。
[1,2,1,3,5,2,4].tally #=> { 1=>2, 2=>2, 3=>1, 5=>1, 4=>1 }
# Other possible usage
(1..6).tally { |i| i%3 } #=> { 0=>2, 1=>2, 2=>2 }
Run Code Online (Sandbox Code Playgroud)
每当你发现有人声称某种东西在这种原始程序中是最快的时候,我总是觉得有趣的是要确认,因为没有确认我们大多数人真的只是在猜测.所以我在这里采用了所有方法并对它们进行了基准测试.
我从一个网页中提取了120个链接的数组,我需要按照计数进行分组,并使用秒= Benchmark.realtime do循环实现所有这些,并且一直都有.
假设链接是我需要计算的数组的名称:
#0.00077
seconds = Benchmark.realtime do
counted_links = {}
links.each { |e| counted_links[e] = links.count(e) if counted_links[e].nil?}
end
seconds
#0.000232
seconds = Benchmark.realtime do
counted_links = {}
links.sort.group_by {|x|x}.each{|x,y| counted_links[x] = y.size}
end
#0.00076
seconds = Benchmark.realtime do
Hash[links.uniq.map{ |i| [i, links.count(i)] }]
end
#0.000107
seconds = Benchmark.realtime do
links.inject(Hash.new(0)) {|h, v| h[v] += 1; h}
end
#0.000109
seconds = Benchmark.realtime do
links.each_with_object(Hash.new(0)) {|e, h| h[e] += 1}
end
#0.000143
seconds = Benchmark.realtime do
links.inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
end
Run Code Online (Sandbox Code Playgroud)
然后一点点红宝石来找出答案:
times = [0.00077, 0.000232, 0.00076, 0.000107, 0.000109, 0.000143].min
==> 0.000107
Run Code Online (Sandbox Code Playgroud)
所以实际上最快的方法,当然是ymmv:
links.inject(Hash.new(0)) {|h, v| h[v] += 1; h}
Run Code Online (Sandbox Code Playgroud)
我相信有更好的方法,
>> arr.sort.group_by {|x|x}.each{|x,y| print "#{x} #{y.size}\n"}
1 2
2 2
3 1
4 1
5 1
Run Code Online (Sandbox Code Playgroud)
根据需要将x和y值分配给哈希.
这应该做
arr = [1,2,1,3,5,2,4]
puts arr.inject(Hash.new(0)) {|h, v| h[v] += 1; h}
#=> {1=>2, 2=>2, 3=>1, 5=>1, 4=>1}
Run Code Online (Sandbox Code Playgroud)
小智 5
仅供记录,我最近在这里阅读.我的解决方案是:Object#tap
Hash.new(0).tap{|h| arr.each{|i| h[i] += 1}}
该#tap
方法将调用者传递给块然后返回它.当你必须逐步构建数组/哈希时,这非常方便.
归档时间: |
|
查看次数: |
31864 次 |
最近记录: |