0

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:

  • the element of the 1st array has only the string before "?" and replace the "." to a space.
  • the element of the 2nd array is the string after "?" and include "?"

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
mu is too short
  • 426,620
  • 70
  • 833
  • 800
Mellon
  • 37,586
  • 78
  • 186
  • 264
  • 3
    it seems pretty trivial, where exactly do you get stuck? show some code. – tokland Nov 04 '11 at 15:38
  • 1
    I agree; along with your previous question, I'd suggest making an effort first. You know how to create arrays, you know a few ways to iterate, you know how to do a replace. There's a [split](http://apidock.com/ruby/String/split) method on string. – Dave Newton Nov 04 '11 at 15:49
  • I was about to post my answer, but agree. Look into the array (hint: map) and string documentation. – Derek Prior Nov 04 '11 at 15:50
  • It looks like you edited the question. What kind of efficiency are you asking for: simplest code or fastest execution time? – David Grayson Nov 04 '11 at 15:57
  • Yep, I added my code already. I am looking for both, simplest code and fastest execution one. Just wanna learn from more experienced one – Mellon Nov 04 '11 at 15:59

5 Answers5

3

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
tokland
  • 66,169
  • 13
  • 144
  • 170
1

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.

coreyward
  • 77,547
  • 20
  • 137
  • 166
0

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.

drummondj
  • 1,483
  • 1
  • 10
  • 11
0
1st_arr = customers.collect{ |name| name.gsub(/\?.*\z/,'').gsub(/\./,' ') }

2nd_arr = customers.collect{ |name| name.match(/\?.*\z/)[0] }
lucapette
  • 20,564
  • 6
  • 65
  • 59
Cecille Manalang
  • 213
  • 3
  • 14
0
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).

steenslag
  • 79,051
  • 16
  • 138
  • 171