Arrays 检查数组x位置的元素是否等于某个值
我正在尝试创建一个以字符串作为输入的方法,如果字符串包含一、二、三、四、五、六、七、八或九,则将它们作为整数计算并相加,例如:Arrays 检查数组x位置的元素是否等于某个值,arrays,ruby,string,loops,Arrays,Ruby,String,Loops,我正在尝试创建一个以字符串作为输入的方法,如果字符串包含一、二、三、四、五、六、七、八或九,则将它们作为整数计算并相加,例如: secret_code("one on one") #=> 2 secret_code("five monkeys in three farms") #=> 8 secret_code("") #=> 0 secret_code("fivethreeone") #=> 0 我想将给定的字符串按单词拆分,并将它们放入数组中,这样我就可以迭代它,检
secret_code("one on one") #=> 2
secret_code("five monkeys in three farms") #=> 8
secret_code("") #=> 0
secret_code("fivethreeone") #=> 0
我想将给定的字符串按单词拆分,并将它们放入数组中,这样我就可以迭代它,检查位置I处的元素是否等于一个数字,并将其对应的值添加到一个变量中。这是我目前的代码:
def secret_code(a)
arr = a.split(/\W+/)
i = 0
l = arr.size
num = 0
puts arr
if !arr.any?
0
end
while i < l do
case arr
when arr[i] == "one"
num += 1
exit
when arr[i] == "two"
num += 2
exit
when arr[i] == "three"
num += 3
exit
when arr[i] == "four"
num += 4
exit
when arr[i] == "five"
num += 5
exit
when arr[i] == "six"
num += 6
exit
when arr[i] == "seven"
num += 7
exit
when arr[i] == "eight"
num += 8
exit
when arr[i] == "nine"
num += 9
exit
end
i+=1
end
puts num
end
secret_code("one on one") #=> 2
secret_code("five monkeys in three farms") #=> 8
secret_code("") #=> 0
secret_code("fivethreeone") #=> 0
我不太确定如何迭代数组。现在,它为所有内容打印0。问题在于:
case arr
when arr[i] == "one"
num += 1
# ...
end
在case语句中,您在每次when之后给出的值将与您在case之后给出的值进行比较。换句话说,您的case语句将首先执行arr[i]==one==arr,然后执行arr[i]==two==arr,依此类推。由于arr[i]==one返回true或false,并且true==arr和false==arr永远不会为true,因此case语句中的任何条件都不会满足
最简单的修复方法是:
case arr[i]
when "one"
num += 1
when "two"
num += 2
when "three"
num += 3
# ...
end
这段代码所做的是将arr[i]的值与1进行比较,然后再与2进行比较,依此类推,从而产生预期的行为
还要注意,我删除了exit。在Ruby中,exit退出程序。我猜您是在尝试像在其他编程语言中使用break一样使用它。这里不需要这样做,因为Ruby case语句不像某些语言中的switch语句那样有故障。在case语句中只有一个when匹配
更多改进
关于您的代码,我还有一些注释:
此代码不执行任何操作:
if !arr.any?
0
end
你不能用0做任何事情,所以它只是消失在虚空中。您可能打算执行return0以尽早从方法返回。更好的成语应该是:
return 0 if arr.empty?
虽然在Ruby中没有必要使用EnumerableAch,但更常见的是使用EnumerableAch迭代数组的元素:
arr.each do |word|
case word
when "one"
# ...
# ...
end
end
通过将case语句视为返回值的表达式,可以使其更加简洁:
num += case arr[i]
when "one" then 1
when "two" then 2
when "three" then 3
# ...
else 0
end
通过使用哈希而不是case语句,您可以使其更加简洁:
word_values = {
"one" => 1, "two" => 2, "three" => 3,
"four" => 4, "five" => 5, "six" => 6,
"seven" => 7, "eight" => 8, "nine" => 9
}
word_values.default = 0
arr.each do |word|
num += word_values[word]
end
这将遍历单词数组,并在单词_值散列中查找每个单词。如果单词不在哈希中,它将返回默认值0
使用单词_值哈希,您还可以执行以下操作:
values = arr.map {|word| word_values[word] }
puts values.reduce(:+)
这使用map将单词数组转换为值数组,例如,三个农场中的五只猴子变为[5,0,0,3,0]。然后,它使用reduce(也称为inject)来计算值之和
现在一起
将所有这些改进放在一起,我们有:
WORD_VALUES = {
"one" => 1, "two" => 2, "three" => 3,
"four" => 4, "five" => 5, "six" => 6,
"seven" => 7, "eight" => 8, "nine" => 9
}
WORD_VALUES.default = 0
def secret_code(str)
str.split(/\W+/)
.map {|word| WORD_VALUES[word] }
.reduce(:+) || 0
end
puts secret_code("one on one") # => 2
puts secret_code("five monkeys in three farms") # => 8
puts secret_code("") # => 0
puts secret_code("fivethreeone") # => 0
在Ruby2.3中,您实际上可以执行.map和WORD_值,这非常简洁
还有另一种方法,效率稍高一些:
def secret_code(str)
str.split(/\W+/).reduce(0) {|sum, word| sum + WORD_VALUES[word] }
end
它在其块形式中使用reduce来查找散列中的每个值,并将其添加到运行总和中
替代方案
这稍微高级一些,但展示了一些其他Ruby功能:
WORD_VALUES = {
"one" => 1, "two" => 2, "three" => 3,
"four" => 4, "five" => 5, "six" => 6,
"seven" => 7, "eight" => 8, "nine" => 9
}
WORD_EXPR = /\b#{Regexp.union(WORD_VALUES.keys)}\b/
def secret_code(str)
str.scan(WORD_EXPR).reduce(0) {|sum, word| sum + WORD_VALUES[word] }
end
这将使用WORD_VALUES数组的键来构建一个大致如下所示的正则表达式:
WORD_EXPR = /\b(one|two|three|four|five|six|seven|eight|nine)\b/
NUMBERS = {
'one' => 1, 'two' => 2, 'three' => 3,
'four' => 4, 'five' => 5, 'six' => 6,
'seven' => 7, 'eight' => 8, 'nine' => 9
}
def secret_code(string)
words = string.split(/\W+/)
words.inject(0) do |sum, word|
sum + NUMBERS.fetch(word, 0)
end
end
puts secret_code('one on one')
#=> 2
puts secret_code('five monkeys in three farms')
#=> 8
puts secret_code('')
#=> 0
puts secret_code('fivethreeone')
#=> 0
然后它使用Stringscan,它返回与正则表达式匹配的所有子字符串,例如,三个农场中的五只猴子。scanWORD_EXPR返回[five,three]。然后使用上面的reduce查找它们的值并求和。我会这样做:
WORD_EXPR = /\b(one|two|three|four|five|six|seven|eight|nine)\b/
NUMBERS = {
'one' => 1, 'two' => 2, 'three' => 3,
'four' => 4, 'five' => 5, 'six' => 6,
'seven' => 7, 'eight' => 8, 'nine' => 9
}
def secret_code(string)
words = string.split(/\W+/)
words.inject(0) do |sum, word|
sum + NUMBERS.fetch(word, 0)
end
end
puts secret_code('one on one')
#=> 2
puts secret_code('five monkeys in three farms')
#=> 8
puts secret_code('')
#=> 0
puts secret_code('fivethreeone')
#=> 0
尝试从数字哈希中获取值,如果关键字不存在,则返回0。它基本上与以下功能相同:
if NUMBERS.key?(word)
0
else
NUMBERS[word]
end
已用0初始化。它迭代数组中的每个元素,并将当前值作为和传递给块。块和的结果+字的值在下一次迭代中用作和的新值 您的case语句是错误的,因为它在Ruby中包含导致运行脚本立即终止的语句 您应该检查case语句的正确语法 此外,您可以使用scan快速扫描字符串以查找匹配项
"five monkeys in three farms".scan(/five|three|four/)
=> ["five", "three"]
然后,您可以将匹配项转换为相应的值,例如使用存储在散列中的映射,并计算结果
numbers = {
"three" => 3,
"four" => 4,
"five" => 5,
}
results = "five monkeys in three farms".scan(/#{numbers.keys.join("|")}/)
=> ["five", "three"]
results.inject(0) { |total, result| total += numbers[result] }
# => 8
这个解决方案有一个警告。它将匹配部分单词,因此,如果需要应用适当的边界,则需要使用它来考虑完整的单词,因此如果某人可以发送字符串,就像在示例中提供的最后一个字符串。 ,代码中的问题已经被其他人回答了。这里有一个替代方案
str = "five monkeys in three farms"
h = { "one=>1", "two"=>2, "three"=>3, "four"=>4, "five"=>5,
"six"=>6, "seven"=>7, "eight"=>8, "nine"=>9 }
str.gsub(/\w+/,h).split.map(&:to_i).reduce(:+)
#=> 8
它使用的是使用散列的形式。步骤如下:
s = str.gsub(/\w+/,h)
#=> "5 3 "
非h键的匹配项将转换为空字符串。空格与\w+/不匹配,因此不受影响
t = s.split
#=> ["5", "3"]
u = t.map(&:to_i)
#=> [5, 3]
u.reduce(:+)
#=> 8
Ruby中有很多。你不必手动操作,而且你很难做到。对于这一点,你可以用它来寻找词语
str.scan(/(\w+)/) { |word|
... do something with word[0] ...
}
然后你需要把这些单词变成数字。在中提供了几种方法。对于生产代码,您应该这样做,但由于这是扫描字符串的练习,最简单的方法是使用一个小表
您的case语句似乎有一些缺陷—请看一下—不要使用exit—它将过早地退出程序。如果你解决了你的问题,摆脱了退出,你就会纠正为什么匆忙选择答案?你这样做可能会阻碍其他有趣的答案,在我看来,当你做出选择时,这对仍在研究答案的读者来说是不体谅的。许多会员在做出选择之前至少要等上几个小时,有时甚至要等上更长的时间。许多会员要等上几天。好的答案需要一段时间才能创建,而且回答的人遍布全球,或者每隔几天就会出现堆栈溢出。基本问题在重复问题的选定答案中得到回答。这个问题的其余部分是如何匹配单词来决定什么是数字单词,什么不是数字单词,这很容易通过哈希或可接受值数组来完成。对于初学者来说,这不是最容易解决的问题。你能补充一些解释吗?我同意这对初学者来说可能很难理解,详细阐述它会很有帮助,但我投+1票,因为它是一个非常聪明和漂亮的实现。但是,需要注意的是,它并不能真正回答用户在代码中遇到问题的原因;我总是试图提供解释,但有时,就像这里一样,我单独展示代码,然后编辑以提供解释。如果字符串是18只猴子,它应该返回零呢?@CarySwoveland就像我说的,在真实代码中,你会使用gem。这不是关于添加数字的问题,对于我链接到的问题,已经有一个完整的其他问题了,这是关于如何在Ruby中扫描字符串的问题。