通过数组有条件地迭代

问题描述:

我想将一个数组分解为一个数组数组。通过数组有条件地迭代

test_ary = %w(101 This is the first label 102 This is the second label 103 This is 
the third label 104 This is the fourth label) 

result = iterate_array(test_ary) 

预期输出:

#⇒ [ 
# "101 This is the first label", 
# "102 This is the second label", 
# "103 This is the third label", 
# "104 This is the fourth label" ] 

我写了下面的方法:

def iterate_array(ary) 
    temp_ary = [] 
    final_ary =[] 
    idx = 0 
    temp_ary.push ary[idx] 
    idx +=1 
    done = ary.length - 1 
    while idx <= done 
     if ary[idx] =~ /\d/ 
      final_ary.push temp_ary 
      temp_ary = [] 
      temp_ary.push ary[idx] 
     else 
      temp_ary.push ary[idx] 
     end 
     idx +=1 
    end 
    final_ary.push temp_ary 
    returned_ary=final_ary.map {|nested_ary| nested_ary.join(" ")} 
    returned_ary 
end 

我认为必须有一个更简单,更优雅的方式。有任何想法吗?

+2

中号嗨,这将帮助你将包括预期的输出,这将有助于清理一些格式错误。 – mwp

+0

对不起。我只是着手格式化。希望我把它清理干净(在Vlad的帮助下) - M –

根据您的函数给出的输出结果,使用%w(101 This is the first label 102 This is the second label 103 This is the third label 104 This is the fourth label).each { |x| puts x }或使用map我得到了相同的结果。如果您可以发布您的预期输出,这将有所帮助。

这将一次遍历数组中的两个元素,当右侧是一个数字时“断开”(切片)它(或者当它被写入时,当右侧不包含任何非零元素时)数字字符)。希望这可以帮助!

test_ary.slice_when { |_, r| r !~ /\D/ }.map { |w| w.join(' ') } 
+0

这是一个非常好用的正则表达式。但是,假设数组在数字时总是应该中断。尽管如此,答案很好。 +1 – Vlad

+1

谢谢@Vlad。它对输入做出了一些有力的假设,但我只能解决原始问题中可用的任何信息! – mwp

+0

谢谢mwp。我想我太依赖ruby-doc.org上的基本Array类文档了。我在ruby-lang.org上找到了关于#slice_when和#slice_between的信息。但我很困惑:当我输入Array.methods时,不应该slice_when,哪个Array应该从Enumerable继承,显示出来吗?它不... –

我会用Enumerable#slice_before

test_ary.slice_before { |w| w =~ /\d/ }.map { |ws| ws.join(" ") } 
# => ["101 This is the first label", "102 This is the second label", "103 This is the third label", "104 This is the fourth label"] 

编辑:作为@mwp说,可以让这个更短:

test_ary.slice_before(/\d/).map { |ws| ws.join(" ") } 
# => ["101 This is the first label", "102 This is the second label", "103 This is the third label", "104 This is the fourth label"] 
+2

非常好!我喜欢这比slice_when更好。 slice_before可以接受一个模式参数,所以它可以简化为'words.slice_before(/ \ d /)'。 – mwp

+0

@mwp谢谢!我不知道。 – Dogbert

▶ test_ary.join(' ').split(/ (?=\d)/) 
#⇒ [ 
# [0] "101 This is the first label", 
# [1] "102 This is the second label", 
# [2] "103 This is the third label", 
# [3] "104 This is the fourth label" 
# ] 
+0

Thx muda。使用正则表达式有很长的路要走 –

+0

欢迎erel,但我无法理解你的意思。 – mudasobwa