使用include?的简短Ruby Case语句将无法工作

10

我有以下代码,其中存在一个小错误,在第一个"when"语句评估为true并应该返回"boats"的情况下,case语句返回值"other"。

我已经看了好久了,一定是个小问题。

CATEGORY_CLASSES = {:boats  => [1, 2, 3, 4, 5, 6],
              :houses => [7, 8, 9, 10],
              :other  => [11,12,13,14,15,16]
             }

category_id = 1

category = case category_id
  when CATEGORY_CLASSES[:boats].include?(category_id); "boats"
  when CATEGORY_CLASSES[:houses].include?(category_id); "houses"
  else "other"
end

谢谢!


你的哈希表中没有 :cars 标签,因此无法返回 "boats"。 - AShelly
4个回答

57

您可以在when语句中按以下方式扩展数组:

category = case category_id
  when *CATEGORY_CLASSES[:boats]; "boats"
  when *CATEGORY_CLASSES[:houses]; "houses"
  else "other"
end

展开运算符很棒,但这可能比if语句效率低。 - MikeJ
1
我更喜欢这种简洁的语法,而不是接受的答案。此外,关于@MikeJ的评论,一个基准测试会很好。 - Cyril Duchon-Doris
2
决定对此进行基准测试。显然,使用数组扩展的情况比较慢,速度慢了1.5倍(在ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux]上进行了测试)。 - Fizvlad

11

case语句通常只是一个if语句的简写。你的可以改写为:

if CATEGORY_CLASSES[:boats].include?(category_id) === category_id
  category = "boats"
elsif CATEGORY_CLASSES[:houses].include?(category_id) === category_id
  category = "houses"
else
  category = "other"
end

以这种形式看待它,你应该清楚地看到问题所在;虽然include?返回一个布尔值,但你却将其与一个整数值进行比较。


3
实际上,case 使用的是 === 而不是 ==,但在这种情况下,差异并不重要。 - sepp2k
@sepp2k 没错,那就是我想写的。 - Daniel Vandersluis

7
(我会忽略你的哈希表实际上不包含任何你检查的键这一事实,并假装你正在检查实际上在哈希表中的键。希望这是正确的假设。)
你似乎误解了case语句的含义。它测试的是case语句对象的值,而不仅仅是运行一些模糊相关的if语句。所有的when子句都与case语句对象使用===进行比较。因此,如果你写CATEGORY_CLASSES[:boats].include?(category_id),那么它意味着if true === category_idif false === category_id(因为include?返回true或false)。
你需要的更像是CATEGORIES.find {|k,v| v.include? category_id}.first.to_s

实际上,Ruby的case语句有两种形式,其中一种确实意味着运行一堆模糊相关的if语句。他可能打算使用另一种case形式,即直接在case后面跟随when的形式。 - Jan M

0

你也可以在这里使用lambda。像这样。

boats = ->(id) { CATEGORY_CLASSES[:boats].include? id }
houses = ->(id) { CATEGORY_CLASSES[:houses].include? id }

category = case category_id
  when boats; "boats"
  when houses; "houses"
  else "other"
end

这是如何工作的?case 调用左操作数上的 ===。在 procs/lambdas 中,===#call 相同。


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