Ruby数组,在我的情况下转换为两个数组

我有一个字符串数组,其中包含“ firstname.lastname?some.xx ”格式字符串:

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

现在,我想使用这个数组生成两个数组,其中:

  • 第一个数组的元素只有“?”之前的字符串 并将“ ”替换为空格
  • 第二个数组的元素是“ ”之后的字符串并包含“

那是我想从 customers 数组中 生成以下两个 数组

 1st_arr = ["aaa bbb", "ccc ddd", "www uuu", ...] 2nd_arr = ["?q21.dd", "?ew3.yt", "?nbg.xcv", ...] 

如果我将customers数组用作方法的参数 ,那么最有效的方法是什么

 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 

function方法:当你在循环中生成结果但是希望它们在不同的数组中分割时, Array#transpose会很方便:

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

无论何时你从另一个构建数组, reduce (aka inject )都是一个很好的帮助:

但有时候,你需要一个好的map (在这种情况下,任何一个都可以,因为你正在构建一个相同大小的数组):

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

这是非常有效的,因为您只是通过客户一次迭代,并且通过+方法不创建大量无关的字符串和数组,从而有效地利用了内存。

Array#collect适合这类事情:

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

但是,你必须做两次初始的c.split(“?”)。 因此,从大量代码的角度来看,它是有效的,但CPU密集度更高。

 1st_arr = customers.collect{ |name| name.gsub(/\?.*\z/,'').gsub(/\./,' ') } 2nd_arr = customers.collect{ |name| name.match(/\?.*\z/)[0] } 
 array1, array2 = customers.map{|el| el.sub('.', ' ').split /(?:\?)/}.transpose 

基于@Tokland的代码,但它避免了额外的变量(通过使用’sub’而不是’gsub’)和重新附加’?’ (通过使用非捕获正则表达式)。