Mellon
Mellon

Reputation: 38842

Ruby array, convert to two arrays in my case

I have an array of string which contains the "firstname.lastname?some.xx" format strings:

customers = ["aaa.bbb?q21.dd", "ccc.ddd?ew3.yt", "www.uuu?nbg.xcv", ...]

Now, I would like to use this array to produce two arrays, with:

That's I want to produce the following two arrays from the customers array:

1st_arr = ["aaa bbb", "ccc ddd", "www uuu", ...]

2nd_arr = ["?q21.dd", "?ew3.yt", "?nbg.xcv", ...]

What is the most efficient way to do it if I use customers array as an argument of a method?

def produce_two_arr customers
  #What is the most efficient way to produce the two arrays

  #What I did:
  1st_arr = Array.new
  2nd_arr = Array.new
  customers.each do |el|
    1st_Str, 2nd_Str=el.split('?')

    1st_arr << 1st_str.gsub(/\./, " ")
    2nd_arr << "?"+2nd_str
  end

  p 1st_arr
  p 2nd_arr
end

Upvotes: 0

Views: 288

Answers (5)

steenslag
steenslag

Reputation: 80065

array1, array2 = customers.map{|el| el.sub('.', ' ').split /(?:\?)/}.transpose

Based on @Tokland 's code, but it avoids the extra variables (by using 'sub' instead of 'gsub') and the re-attaching of '?' (by using a non-capturing regex).

Upvotes: 0

Cecille Manalang
Cecille Manalang

Reputation: 223

1st_arr = customers.collect{ |name| name.gsub(/\?.*\z/,'').gsub(/\./,' ') }

2nd_arr = customers.collect{ |name| name.match(/\?.*\z/)[0] }

Upvotes: 0

coreyward
coreyward

Reputation: 80041

Anytime you're building an array from another, reduce (a.k.a. inject) is a great help:

But sometimes, a good ol' map is all you need (in this case, either one works because you're building an array of the same size):

a, b = customers.map do |customer|
  a, b = customer.split('?')
  [a.tr('.', ' '), "?#{b}"]
end.transpose

This is very efficient since you're only iterating through customers a single time and you are making efficient use of memory by not creating lots of extraneous strings and arrays through the + method.

Upvotes: 1

tokland
tokland

Reputation: 67850

Functional approach: when you are generating results inside a loop but you want them to be split in different arrays, Array#transpose comes handy:

ary1, ary2 = customers.map do |customer|
  a, b = customer.split("?", 2)
  [a.gsub(".", " "), "?" + b]
end.transpose

Upvotes: 3

drummondj
drummondj

Reputation: 1483

Array#collect is good for this type of thing:

arr1 = customers.collect{ |c| c.split("?").first.sub( ".", "" ) }
arr2 = customers.collect{ |c| "?" + c.split("?").last }

But, you have to do the initial c.split("?") twice. So, it's effecient from an amount of code point of view, but more CPU intensive.

Upvotes: 0

Related Questions