jsinnott
jsinnott

Reputation: 201

Ruby: How do I convert a string (ARGV) representation of integers and ranges to an array of integers

In Ruby, how can I take an array of tokens representing either integers or ranges and parse them into an array of integers that include each integer and each element in each range?

Example: Given input [ "5", "7-10", "24", "29-31"]

I'd like to produce output [ 5, 7, 8, 9, 10, 24, 29, 30, 31 ]

Thanks.

Upvotes: 3

Views: 2186

Answers (4)

ghostdog74
ghostdog74

Reputation: 342433

>> [ "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]

Upvotes: 0

coder_tim
coder_tim

Reputation: 1720

[ "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

Upvotes: 3

Mike Trpcic
Mike Trpcic

Reputation: 25659

Something like the following should work. Just pass your input into the method and get an array of integers out. I've kept it intentionally verbose so you can see the logic.

Edit: I've added comments to the code.

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

Running this code on your example input produces your example output, so I believe it's spot on.

Upvotes: 1

Jacob Relkin
Jacob Relkin

Reputation: 163258

Well, this might need a bit of work, actually. I'll take a crack at it now:

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

Upvotes: 1

Related Questions