我有一个类似于以下内容的txt文件:
f1, max, inputs: 10 2 4
f2, sum, inputs: 2 4 5
f3, prod, inputs: 6 5
我应该找到max
所述行的最大值(10),打印sum
所在的数字的总和(11),以及prod
所在的数字的总和{1}}是(30)。
我的代码如下所示:
f = File.open("test.txt") or die "Unable to open file..."
contentArray=[]
f.each_line {|line|
contentArray.push line
}
i=0
while i<contentArray.size() do
if contentArray[i].include? "max"
print "max is here"
i+=1
elsif contentArray[i].include? "sum"
print "sum is here"
i+=1
elsif contentArray[i].include? "prod"
print "prod is here"
i+=1
end
end
我可以找到哪一行有max,sum或prod字符串,但我不知道如何从最后剪掉整数并用它们做数学运算。
答案 0 :(得分:1)
<强>代码强>
def print_totals(fname)
File.foreach(fname) do |line|
_, op, _, *a = line.split(/, *|: *| +(?=\d)/)
a.map!(&:to_i)
tot = a.reduce do |t,n|
case op
when 'max' then [t,n].max
when 'sum' then t+n
when 'prod' then t*n
end
end
puts "%s %s = %d" % [op, a, tot]
end
end
line.split(/, *|: *| +(?=\d)/)
读取&#34;将line
拆分为a)逗号后跟零个或多个空格或b)冒号后跟零个或多个空格或c)后跟一个或多个空格用数字&#34; ((?=\d)
是正向前瞻)。该行的操作如下。
line = "f1, max, inputs: 10 2 4"
_, op, _, *a = line.split(/, *|: *| +(?=\d)/)
#=> ["f1", "max", "inputs", "10", "2", "4"]
op #=> "max"
a #=> ["10", "2", "4"]
示例强>
首先创建一个测试文件。
contents =<<-_
f1, max, inputs: 10 2 4
f2, sum, inputs: 2 4 5
f3, prod, inputs: 6 5
_
FName = 'temp'
File.write(FName, contents)
#=> 69
确认其内容。
puts File.read(FName)
f1, max, inputs: 10 2 4
f2, sum, inputs: 2 4 5
f3, prod, inputs: 6 5
打印所需的结果。
print_totals FName
max [10, 2, 4] = 10
sum [2, 4, 5] = 11
prod [6, 5] = 30
答案 1 :(得分:1)
考虑一下:
content_array = [
'f1, max, inputs: 10 2 4',
'f2, sum, inputs: 2 4 5',
'f3, prod, inputs: 6 5'
]
我会解决这样的基本问题:
content_array.each do |li|
values = li.scan(/\b \d+ \b/x).map(&:to_i)
operation, result = case li
when /\b max \b/x
['max', values.max]
when /\b sum \b/x
['sum', values.sum]
when /\b prod \b/x
['prod', values.inject(:*)]
end
puts "#{operation}: #{result}"
end
哪个输出:
max: 10
sum: 11
prod: 30
这样做会处理更多数字,这些数字会添加到行的末尾,而不会更改代码。
如果我添加了其他记录:
'f4, prod, inputs: 6 5 4 3 2'
我会得到:
prod: 720
打破它:
values = li.scan(/\b \d+ \b/x) # => ["10", "2", "4"], ["2", "4", "5"], ["6", "5"]
.map(&:to_i) # => [10, 2, 4], [2, 4, 5], [6, 5]
/\b \d+ \b/x
是一个正在搜索独立数字的正则表达式模式。
答案 2 :(得分:0)
给这样的东西一个镜头:
content_ary.each do |content_str|
segments_ary = content_str.split(':')
integers_ary = segments_ary[1].strip.split(' ').map{|int_str| int_str.to_i}
tags_ary = segments_ary[0].strip.split(',')
case tags_ary[1].strip
when "max"
puts "max is here"
puts "#{integers_ary}"
when "sum"
puts "sum is here"
puts "#{integers_ary}"
when "prod"
puts "prod is here"
puts "#{integers_ary}"
end
end
首先,使用snake_case
代替camelCase
会更加红润。所以,content_ary
,而不是contentArray
。
然后,执行content_ary.each do |content_str|
而不是while i < contentArray.size()
。然后你不必弄乱机智i+=1
。
接下来,
segments_ary = content_str.split(':')
将每一行拆分为一个双元素数组,每个元素在“:”的左侧和右侧开始内容。
integers_ary = segments_ary[1].strip.split(' ').map{|int_str| int_str.to_i}
在右侧提取整数:
segments_ary[1] <= selects the right-hand side
strip <= removes leading and trailing white spaces
split(' ') <= creates an array of strings
map{|int_str| int_str.to_i} <= converts the strings to integers
然后: tags_ary = segments_ary [0] .strip.split(',')
提取':'左侧的标签。
现在,使用case
语句而不是if... elsif... elsif
。
答案 3 :(得分:0)
如果可以肯定的话,第一个字段(&#39; f1&#39;,....)总是以字母字符开头,一个便宜的解决方案就是简单地在空格上分割:
fields = line.split(' ')
或
fields = line.split(/\s/)
取决于你的口味。
然后按
获取数字numbers = fields.select { |element| /^\d/ =~ element }.map(&:to_i)
作为副作用,您还可以免费获得操作符,例如
case fields[1]
when 'sum,'
result = numbers.reduce(:+)
when 'max,'
...
end
当然,这假设输入严格对应于此格式。如果无法确保这一点(例如因为输入文件是由人手动创建的),您应该在输入格式上添加一些卫生检查。