ruby 数组到哈希:字数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9480852/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 04:50:04  来源:igfitidea点击:

Array to Hash : words count

ruby

提问by demas

I have array of words and I want to get a hash, where keys are words and values are word count.

我有一个单词数组,我想得到一个哈希值,其中键是单词,值是单词计数。

Is there any more beautiful way then my:

有没有比我的更漂亮的方式:

result = Hash.new(0)
words.each { |word| result[word] += 1 }
return result

回答by tokland

The imperative approach you used is probably the fastest implementation in Ruby. With a bit of refactoring, you can write a one-liner:

您使用的命令式方法可能是 Ruby 中最快的实现。通过一些重构,您可以编写一个单行代码:

wf = Hash.new(0).tap { |h| words.each { |word| h[word] += 1 } }

Another imperative approach using Enumerable#each_with_object:

另一种命令式方法使用Enumerable#each_with_object

wf = words.each_with_object(Hash.new(0)) { |word, acc| acc[word] += 1 }

A functional/immutable approach using existing abstractions:

使用现有抽象的功能/不可变方法:

wf = words.group_by(&:itself).map { |w, ws| [w, ws.length] }.to_h

Note that this is still O(n)in time, but it traverses the collection three times and creates two intermediate objects along the way.

请注意,这在时间上仍然是O(n),但它遍历了集合 3 次,并在此过程中创建了两个中间对象。

Finally: a frequency counter/histogram is a common abstraction that you'll find in some libraries like Facets: Enumerable#frequency.

最后:频率计数器/直方图是一种常见的抽象,您可以在某些库中找到,例如 Facets: Enumerable#frequency

require 'facets'
wf = words.frequency

回答by Baldrick

With inject:

inject

str = 'I have array of words and I want to get a hash, where keys are words'
result = str.split.inject(Hash.new(0)) { |h,v| h[v] += 1; h }

=> {"I"=>2, "have"=>1, "array"=>1, "of"=>1, "words"=>2, "and"=>1, "want"=>1, "to"=>1, "get"=>1, "a"=>1, "hash,"=>1, "where"=>1, "keys"=>1, "are"=>1}

I don't know about the efficiency.

我不知道效率如何。

回答by Pawan

Posted on a related question, but posting here for visibility as well:

发布在相关问题上,但也发布在这里以提高知名度:

Ruby 2.7 onwards will have the Enumerable#tallymethod that will solve this.

Ruby 2.7 以后Enumerable#tally会有解决这个问题的方法。

From the trunk documentation:

从主干文档

Tallys the collection. Returns a hash where the keys are the elements and the values are numbers of elements in the collection that correspond to the key.

统计集合。返回一个散列,其中键是元素,值是集合中与键对应的元素数。

["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}

回答by Boris Lopez

irb(main):001:0> %w(foo bar foo bar).each_with_object(Hash.new(0)) { |w, m| m[w] += 1 }
=> {"foo"=>2, "bar"=>2}

as @mfilej said

正如@mfilej 所说