如何将函数应用于数组并形成两个单独的数组?

我正在使用Ruby 2.4。 我有一个包含字符串数据元素的数组,看起来像

["a word1 word2", "b eff", "a idaho orange", "new old shoe", "b mars", ...] 

我想从上面形成两个数组,将一个函数( .split(/^(a|b)[[:space]]*/i )应用于数组的每个元素。但是,我无法弄清楚如何形成两个独立的arrays。以下

 arr.map{ |x| x.split(/^(a|b)[[:space]]*/i) } 

只产生一个数组,每个元素前面都有一个空白元素。 理想情况下,我希望输出为两个数组

 ["a", "b", "a", "", "b", ...] ["word1 word2", "eff", "idaho orange", "new old shoe", "mars", ...] 

试试这个

 arr.map { |x| a, b, c = x.partition(/^[ab]\s+/); [b.strip, a + c] }.transpose 

这是如何运作的?

  • partition将字符串拆分为匹配前,匹配和后匹配
  • b.strip是没有尾随空格的匹配
  • a + c是完整字符串(如果匹配前匹配完整字符串没有匹配)或匹配后
  • [..., ...]创建一个元组,从而创建一个元组数组
  • transpose切换2D数组的行和列

仅限正则表达式

这是我能找到的最短的:

 a1, a2 = arr.map{ |x| x.match(/((?:^[ab](?= ))?) *(.*)/).captures}.transpose 

此示例现在适用于"activity""ball" 。 它会检查字符串开头的ab之后是否紧跟一个空格。

分裂和逻辑

另一种变体是:

 a1, a2 = arr.map do |x| parts = x.split(/(?<=^a|^b) +/) parts.unshift('') if parts.size == 1 parts end.transpose