Ruby/RoR - 计算数组中元素出现的次数

19

我有一个哈希值

{1=>true, 7=>false, 6=>true, 4=>false}

或者一个类似的数组

[1, true], [7, false], [6, true], [4, false]]

或者

[true, false, true, false].

如何找到数组中 true 的个数?


2
从 Ruby 2.7 开始,您可以使用 Enumerable#tally。更多信息请参见此处 - SRack
8个回答

27
为了计算元素数量,显然必须遍历集合。由于迭代 Hash 会产生两个元素的Array,因此前两个元素实际上是完全相同的。
{ 1 => true, 7 => false, 6 => true, 4 => false }.count(&:last)
[[1, true], [7, false], [6, true], [4, false]].count(&:last)

对于简单的Array情况,你可以像这样做:

[true, false, true, false].count(true)

当然,这个 Array 与您上面的 HashHash#values 相同,因此您也可以在其上使用相同的方法:

{ 1 => true, 7 => false, 6 => true, 4 => false }.values.count(true)

如果你不知道你将得到其中的哪一个,你可以使用类似这样的代码:

{ 1 => true, 7 => false, 6 => true, 4 => false }.flatten.count(true)
[[1, true], [7, false], [6, true], [4, false]].flatten.count(true)
[true, false, true, false].flatten.count(true)

非常棒的解决方案,感谢所有寻找答案的人 :) - sidney

7

使用Enumerable#count方法:

hash.values.count(true)
array_of_pairs.map { |k, v| v }.count(true)
plain_array.count(true)

更冗长,但不会创建中间数组:

hash_or_array_of_pairs.inject(0) { |acc, (k, v)| acc + (v == true ? 1 : 0) }

4

更简单:

hash.values.count(true)

array.flatten.count(true)

这适用于上述所有情况。


是的,但在具有成对数组的情况下,array.flatten.count(true) 在概念上很奇怪,因为它还考虑了键(成对中的第一项)。我知道那里永远不应该出现 true,但还是... - tokland
如果有人担心键可能包含true,尽管这很不可能,你可以这样做:Hash[array].values.count(true) - Mark Thomas

4

Ruby 2.7+

在 Ruby 2.7 版本中,新增了 Enumerable#tally 方法(可能还有 tally_by)来实现此目的。这里有一个很好的总结:链接

关于最终的实现是否使用 tallytally_by 来提供块的讨论可以在这里找到。

在这种情况下:

# or hash.tally_by if that's the accepted method for block form
hash.tally { |k, v| v }
# => { true => 2, false => 2 }

发布的新功能文档在这里

希望能帮到有需要的人!


2

关于哈希:

{ :a => true, :b => true, :c => false }.select{ |k,v| v }.length
 => 2

对于数组:

[true, false, false, true, true].select{ |o| o }.length
 => 3

另一种方法(使用否定进行测试):

[true, false, false, true, true].reject{ |o| o != true }.length
 => 3

1
一种方法(在此之前,您的哈希需要首先调用.to_a才能使其工作):
[[1, true], [7, false], [6, true], [4, false]].flatten.select{|s| s == true }.size

请注意,s == true 可以简化为 s - Cadoiz

0

哈希:

my_hash.values.select(&:present?).size

2D数组:

my_2d_array.map(&:last).select(&:present?).size

my_2d_array.select { |_first, last| last.present? }.size

一维数组:

array.select(&:present?).size


0
我正在努力提供一个更一般的答案:计算每个元素的数量。我仍然使用2.6.6版本,所以其他人也没有2.7.x版本。 准备工作:
values_of_hash = {1=>true, 7=>false, 6=>true, 4=>false}.values # also works with the `.map` command from the line below
values_of_array_of_pairs = [[1, true], [7, false], [6, true], [4, false]].map { |k, v| v } # or the `.inject` command from this answer: https://dev59.com/rG855IYBdhLWcg3wMBLV#4488905
values_of_2d = [[1, true], [7, false], [6, true], [4, false]].map(&:last) # similar idea from https://dev59.com/rG855IYBdhLWcg3wMBLV#4490032
values_of_2d = {1=>true, 7=>false, 6=>true, 4=>false}.map(&:last) # both a hash and an array of pairs hold the second value in `.last`
values_of_array = [true, false, true, false]

现在你可以直接使用
def my_tally(values)
  Set.new(values).map {|unique_value| [unique_value, values.count(unique_value)]}
end
# replace `_xy` with anything of the above like e.g. `_array`
my_tally values_of_xy
# => [[true, 2], [false, 2]]

这对于任意数据也适用。也许你想要分析这个:
values_of_xy = {1=>:banana, 2=>:cherry, 3=>:apple, 4=>:cherry, 5=>:banana, 6=>:cherry}.values
my_tally values_of_xy
# => [[:banana, 2], [:cherry, 3], [:apple, 1]]

对于 Ruby 2.7+ 版本来说, 你显然应该使用 tally


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接