假设我有一个像这样的字符串数组:
array = ["foo", "(bar)", "baaz", "quux", "herp", "(derp)"]
我需要加入以"开头的项目("与之前的项目一起获得输出,如下所示:
["foo (bar)", "baaz", "quux", "herp (derp)"]
我想它必须类似于获取与/^\(/
匹配的数组项的索引,然后在块中迭代原始数组,加入index-1..index
处的项目,并在index
处删除
答案 0 :(得分:5)
array.slice_before{|s| !s.start_with?("(")}.map{|a| a.join(" ")}
# => ["foo (bar)", "baaz", "quux", "herp (derp)"]
答案 1 :(得分:4)
从另一个方向看 - 连接整个字符串,然后沿着后面没有(
的空格拆分:
array.join(' ').split(/ (?!\()/)
# => ["foo (bar)", "baaz", "quux", "herp (derp)"]
答案 2 :(得分:1)
我无法改进@ sawa的答案,但我可以提供一种替代方法,一些读者可能会在另一个地方找到其他有用的方法:
array = ["foo", "(bar)", "baaz", "quux", "herp", "(derp)"]
arr = []
enum = array.each
loop do
arr << enum.next
next_up = enum.peek
if next_up[0] == ?(
arr[-1] += (" " + next_up)
enum.next
end
end
arr #=> ["foo (bar)", "baaz", "quux", "herp (derp)"]
这就是发生的事情。
arr = []
enum = array.each
#=> #<Enumerator: ["foo", "(bar)", "baaz", "quux", "herp", "(derp)"]:each>
现在让我们逐步完成循环,直到引发StopIteration
异常:
s = enum.next #=> "foo"
arr << s #=> ["foo"]
next_up = enum.peek #=> "(bar)"
next_up[0] == ?( #=> true
arr[-1] += (" " + next_up) #=> "foo (bar)"
arr #=> ["foo (bar)"]
enum.next #=> "(bar)" (discard)
s = enum.next #=> "baaz"
arr << s #=> ["foo (bar)", "baaz"]
next_up = enum.peek #=> "quux"
next_up[0] == ?( #=> false
s = enum.next #=> "quux"
arr << s #=> ["foo (bar)", "baaz", "quux"]
next_up = enum.peek #=> "herp"
next_up[0] == ?( #=> false
s = enum.next #=> "herp"
arr << s #=> ["foo (bar)", "baaz", "quux", "herp"]
next_up = enum.peek #=> "(derp)"
next_up[0] == ?( #=> true
arr[-1] += (" " + next_up) #=> "herp (derp)"
arr #=> ["foo (bar)", "baaz", "quux", "herp (derp)"]
enum.next #=> "(derp)" (discard)
s = enum.next #=> StopIteration: iteration reached an end
StopIteration
异常由Kernel#loop通过打破循环来处理。
arr #=> ["foo (bar)", "baaz", "quux", "herp (derp)"]
答案 3 :(得分:1)
这是另一种方式,使用Enumerable#chunk。我假设数组的第一个元素的第一个字符不是(
,但是如果该假设不正确,该方法当然可以被修改。
<强>代码强>
def doit(array)
array.chunk { |s| s[0] == ?( }
.map(&:last)
.each_slice(2)
.map { |arr| (arr.size == 2) ? [arr.first[0..-2],
[arr.first.last, *arr.last].join(' ')] : arr }
.flatten
end
<强>实施例强>
array = ["foo", "(bar)", "baaz", "quux", "herp", "(derp)"]
doit(array) #=> ["foo (bar)", "baaz", "quux", "herp (derp)"]
array = ["foo", "(bar)", "(anther bar)", "quux"]
doit(array) #=> ["foo (bar) (anther bar)", "quux"]
<强>解释强>
array = ["foo", "(bar)", "baaz", "quux", "herp", "(derp)"]
enum1 = array.chunk { |s| s[0] == ?( }
#=> #<Enumerator: #<Enumerator::Generator:0x00000101142ce0>:each>
enum1.to_a # elements to be enumerated (for information only)
#=> [[false, ["foo"]], [true, ["(bar)"]],
# [false, ["baaz", "quux", "herp"]], [true, ["(derp)"]]]
a = enum1.map(&:last)
#=> [["foo"], ["(bar)"], ["baaz", "quux", "herp"], ["(derp)"]]
enum2 = a.each_slice(2)
#=> #<Enumerator: [["foo"], ["(bar)"], ["baaz", "quux", "herp"],
# ["(derp)"]]:each_slice(2)>
enum2.to_a # elements to be enumerated (for information only)
#=> [[["foo"], ["(bar)"]], [["baaz", "quux", "herp"], ["(derp)"]]]
c = enum2.map { |arr| (arr.size==2) ? [arr.first[0..-2],
[arr.first.last, *arr.last].join(' ')] : arr }
#=> [[[], "foo (bar)"], [["baaz", "quux"], "herp (derp)"]]
c.flatten
#=> ["foo (bar)", "baaz", "quux", "herp (derp)"]