Ruby - 统计数组中包含两个字符中任意一个的字符串数量

3

我有这个数组

@a = ["P1 - D", "P3 - M", "P1 - D", "P1 - M", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - M", "P2 - D", "P2 - D", "P2 - D", "P2 - M", "P2 - M", "P3 - D", "P3 - D", "P - D", "P1 - M", "P - D", "P - D", "Post - D", "S1 - D", "P1 - M"]

每个字符串基于 Page# - Device。因此,P1-D 是:Page1-桌面 和 P3-M 是:Page3-移动设备。
如何查找数组中有多少个字符串包含 D 或 M?

也许值得写明回答是什么,你需要一个总数吗?例如27或类似{"D"=>20, "M"=>7}的东西。 - Kris
你需要编辑标题,使其与问题一致。也许可以改为:“计算数组中包含两个字符中任意一个的字符串数量。” - Cary Swoveland
当然,谢谢 @CarySwoveland - Rubioli
5个回答

4
a.group_by { |e| e[-1] }.each_with_object({}) { |(k, v), hash| hash[k] = v.count }
#=> {"D"=>20, "M"=>7}

步骤:
groups = a.group_by { |e| e[-1] }
# {
#   "D"=> ["P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P2 - D", "P2 - D", "P2 - D", "P3 - D", "P3 - D", "P - D", "P - D", "P - D", "Post - D", "S1 - D"],
#   "M"=> ["P3 - M", "P1 - M", "P1 - M", "P2 - M", "P2 - M", "P1 - M", "P1 - M"]
# }

group_counts = groups.each_with_object({}) { |(k, v), hash| hash[k] = v.count }
#=> {"D"=>20, "M"=>7}

group_counts['M']
#=> 20

编辑

使用Ruby 2.4+,您可以利用Hash#transform_values(感谢Alex Golubenko :)):

a.group_by { |e| e[-1] }.transform_values(&:size)
#=> {"D"=>20, "M"=>7}

@user6589814 那很奇怪... 你可以使用 group_by{ |el| el[-1] } - Andrey Deineko
a.group_by { |e| e[-1] }.transform_values(&:size) 的翻译是:a.group_by { |e| e[-1] }.transform_values(&:size) - Oleksandr Holubenko
@AlexGolubenko transform_values!! 太棒了,以前没用过。 - Andrey Deineko
String#last 不是 Rails 的方法吗? - Eric Duminil
@EricDuminil 这就是为什么它对 OP 不起作用的原因,我在 Rails 控制台中进行了测试,谢谢!编辑 - Andrey Deineko
显示剩余5条评论

3
可能的解决方案:
@a.group_by { |e| e[-1] }.map {|e, a| [e, a.size]}.to_h
=> {"D"=>20, "M"=>7}

2
@a = ["P1 - D", "P3 - M", "P1 - D", "P1 - M", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - D", "P1 - M", "P2 - D", "P2 - D", "P2 - D", "P2 - M", "P2 - M", "P3 - D", "P3 - D", "P - D", "P1 - M", "P - D", "P - D", "Post - D", "S1 - D", "P1 - M"]
@a.count { |string| string.match(/D|M/) }
#=> 27

我喜欢这种方法,因为它高效且易读。在 count 参数放在最前面同时告诉了读者你要做什么。在 Ruby v2.4+ 中,你可以使用 string.match? /D\M/ 代替,这可能更易读。当然你也可以使用 /[DM]/ 替代 /D}M/。我建议你删除第一行。由于 OP 已经定义了 @a,所以这是多余的,而且会让你的答案不够美观。 - Cary Swoveland

1
@a.select { |word| word.include?('D') || word.include?('M') }.size
# => 27

1
如果你只需要总数,你可以使用:

@a.grep(/D|M/).count
#=> 27

如果您想要小计,这应该是最有效的方法,因为它不会创建任何临时数组:
@a.each_with_object(Hash.new(0)) { |string, count| count[string[-1]] += 1 }
#=> {"D"=>20, "M"=>7}

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