Ruby:如何将字符串(ARGV)表示的整数和范围转换为整数数组

3
在Ruby中,我该如何将一个由表示整数或范围的令牌数组解析为包含每个整数和每个范围中的每个元素的整数数组?
例如:给定输入 [ "5", "7-10", "24", "29-31"],我想要产生输出[ 5, 7, 8, 9, 10, 24, 29, 30, 31 ]
谢谢。
4个回答

3
[ "5", "7-10", "24", "29-31"].map{|x| x.split("-").map{|val| val.to_i}}.map{ |y| Range.new(y.first, y.last).to_a}.flatten

简洁。优雅。棒极了。谢谢 :) - jsinnott

1

类似以下代码应该可以工作。只需将您的输入传递到方法中并获取一个整数数组即可。我故意保持它冗长,以便您可以看到逻辑。

编辑:我已经在代码中添加了注释。

def generate_output(input)
    output = []
    input.each do |element|
        if element.include?("-")
            # If the number is a range, split it
            split = element.split("-")
            # Take our split and turn it into a Ruby Range object, then an array
            output << (split[0].to_i..split[1].to_i).to_a
        else
            # If it's not a range, just add it to our output array
            output << element.to_i
        end
    end
    # Since our ranges will add arrays within the output array, calling flatten
    # on it will make it one large array with all the values in it.
    return output.flatten
end

在您的示例输入上运行此代码会生成您的示例输出,因此我相信它是正确的。

我正在字面上写下完全相同的答案!+1 - Jacob Relkin

1

嗯,实际上这可能需要一些工作。我现在会试着解决它:

def parse_argv_list(list)
   number_list = []
   list.each do |item|
      if item.include?('-')
         bounds = item.split('-')
         number_list.push((bounds[0].to_i..bounds[1].to_i).to_a)
      else
         number_list.push(item.to_i)
      end
   end
   number_list.flatten
end

0
>> [ "5", "7-10", "24", "29-31"].map{|x|x.gsub!(/-/,"..");x[".."]?(eval x).to_a : x.to_i}.flatten
=> [5, 7, 8, 9, 10, 24, 29, 30, 31]

不错!但是 eval 让我有点紧张。我正在使用它来解析 ARGV,所以我认为用户可以很容易地注入恶意代码。 - jsinnott
不,如果在实际展平之前对ARGV进行消毒(例如,检查所有ARGV是否为数字),则使用应该是安全的。重要的不是你使用什么,而是你如何使用它。 - ghostdog74

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