如何在一行的末尾切断int

时间:2017-06-04 19:16:42

标签: ruby

我有一个类似于以下内容的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字符串,但我不知道如何从最后剪掉整数并用它们做数学运算。

4 个答案:

答案 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

当然,这假设输入严格对应于此格式。如果无法确保这一点(例如因为输入文件是由人手动创建的),您应该在输入格式上添加一些卫生检查。