在纸牌游戏桥中,给了四张纸牌点值:杰克:1,皇后:2,国王:3,王牌:4。给定与一手纸牌相对应的字符串数组(纸牌表示为:[“ 2”,“ 3”,“ 4”,“ 5”,“ 6”,“ 7”,“ 8”,“ 9”,“ 10”,“ J”,“ Q”,“ K”, “ A”]),返回该手的高牌点总数。
我可以使用while
循环解决这个简单的问题,但我想学习如何使用.each
遍历数组,这是我的代码不起作用>
def high_card_points(hand)
sum = 0
hand.each do |i|
if hand[i] == "J"
sum += 1
elsif hand[i] == "Q"
sum += 2
elsif hand[i] == "K"
sum += 3
elsif hand[i] == "A"
sum += 4
end
end
sum
end
现在,当我运行它时,出现错误no implicit conversion of String into Integer
。我应该如何以正确的方式做到这一点?
答案 0 :(得分:2)
这里的问题是,当您使用块内的每个变量时,是数组内的对象而不是索引,因此可以按以下方式工作:
def high_card_points(hand)
sum = 0
hand.each do |card|
if card == "J"
sum += 1
elsif card == "Q"
sum += 2
elsif card == "K"
sum += 3
elsif card == "A"
sum += 4
end
end
sum
end
,如果您执行撬动操作
[5] pry(main)* => :high_card_points
[6] pry(main)> high_card_points(cards)
=> 10
您也可以像使用each_index
一样使用索引。但是您也可以采用其他对象功能的方法:
您可以创建您的课程或对课程字符串进行猴子补丁:
class String
def card_points
case self
when 'J'
1
when 'Q'
2
when 'K'
3
when 'A'
4
else
0
end
end
end
然后按以下步骤操作:
[31] pry(main)> cards.map(&:card_points).inject(0, :+)
=> 10
答案 1 :(得分:1)
错误消息指出“ TypeError(没有将String隐式转换为Integer)”,并且在行hand[i] == "J"
中引发了异常。由each
传递到块并分配给块变量i
的第一个元素是i = hand.first #=> "2"
。因此,我们有hand["2"] == "J"
,或者实际上是hand.[]("2")
,但是方法Array#[]要求其参数为整数,并且“没有将String隐式转换为Integer”。>
现在让我解决您问题的另一个方面。
arr = ["2","3","4","5","6","7","8","9","10","J","Q","K","A"]
您可以编写以下内容。
arr.reduce(0) do |tot, s|
tot +
case s
when "J" then 1
when "Q" then 2
when "K" then 3
when "A" then 4
else 0
end
end
#=> 10
我能听到你的声音。您是在说:“我说过我想使用.each
!”。好吧,你有!让我解释一下。
arr
是类Array
的实例。 Array
已Module#include了模块Enumerable,这就是为什么我们可以在arr
上调用实例方法Enumerable#reduce的原因。 (Array.included_modules #=> [Enumerable, Kernel]
。
与Enumerable
中的所有其他实例方法一样,Enumerable#reduce(也称为inject
)要求接收者是类Enumerator的实例,但是arr
是Array
而不是Enumerator
的实例。 Ruby绕过此问题的方法如下。在reduce
上调用arr
时,她发现arr
不是Enumerator
的实例,因此她检查arr
是否具有方法{{1 }}(即each
的类arr
是否具有实例方法Array
)。确实如此,因此她在each
上调用each
以获取
arr
我们现在有了可以在其上调用enum = arr.each
#=> #<Enumerator: ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J",
# "Q", "K", "A"]:each>
的枚举器:
reduce
您看不到enum.reduce(0) do |tot, s|
tot +
case s
when "J" then 1
when "Q" then 2
when "K" then 3
when "A" then 4
else 0
end
end
#=> 10
被调用,但确实可以。我们可以通过在没有方法Array#each
的类中包含Enumerable
来确认这一点,然后看看会发生什么。
each
这就是为什么每个包含class C
include Enumerable
end
c = C.new
#=> #<C:0x0000000002a118a8>
c.reduce {}
#=> NoMethodError (undefined method `each' for #<C:0x0000000002a118a8>)
class C
def each
end
end
c.reduce {}
#=> nil
的类都必须具有返回枚举器的实例方法Enumerable
的原因,并且为什么要在each
的实例方法之前在该类的实例上调用each
1}}。