Arrays 在Ruby中,如何根据条件合并数组中的连续标记?

Arrays 在Ruby中,如何根据条件合并数组中的连续标记?,arrays,ruby,merge,Arrays,Ruby,Merge,这是Ruby 2.4的一部分。我有一个字符串数组,如果连续元素以特殊字符开头或结尾,我想融合它们。例如,如果我的特殊字符是“&”,我有一个数组 ["a &", "b", "c", "d"] 我希望结果是 ["a & b", "c", "d"] ["a & b", "c"] ["a & b", "c"] 类似地,如果数组是 ["a", "&", "b", "c"] ["&", "b", "c"] 我希望结果是 ["a & b",

这是Ruby 2.4的一部分。我有一个字符串数组,如果连续元素以特殊字符开头或结尾,我想融合它们。例如,如果我的特殊字符是“&”,我有一个数组

["a &", "b", "c", "d"]
我希望结果是

["a & b", "c", "d"]
["a & b", "c"]
["a & b", "c"]
类似地,如果数组是

["a", "&", "b", "c"]
["&", "b", "c"]
我希望结果是

["a & b", "c", "d"]
["a & b", "c"]
["a & b", "c"]
如果数组是

["a", "& b", "c"]
我希望结果是

["a & b", "c", "d"]
["a & b", "c"]
["a & b", "c"]
但是,如果数组是

["a", "&", "b", "c"]
["&", "b", "c"]
结果应该是

["&", "b", "c"]
因为在我的特殊角色之前没有非特殊元素。所以我尝试了这个方法

2.4.0 :012 >   words = ["a", "&", "b", "d"]
 => ["a", "&", "b", "d"]
2.4.0 :013 > SPECIAL_TOKENS = %w(&).freeze
 => ["&"]
2.4.0 :014 > words = words.chunk_while { |i, _| i.end_with?(*SPECIAL_TOKENS) }.map(&:join)
 => ["a", "&b", "d"]

但正如您所看到的,它并没有将中的第一个元素与其余元素融合(而且我在“&”和“b”之间丢失了一个空格)。我是否可以对上述内容进行任何调整,以使其如我所期望的那样工作?

这是一个相当冗长的问题,但通过了您的测试。该方法将数组和特殊字符作为参数。初始的
join.split.reject.map
将数组“标准化”为剥离的单个元素,除了两边都有空格的特殊字符。然后我们申请两次


这里有两种方法。我假设,与示例中一样,数组中没有任何元素(字符串)以空格开头或结尾

#1

def join_some(arr, join_ch='&')
  arr.drop(1).each_with_object([arr.first]).with_index(1) do |(s,a),i|
    if (s[0] == join_ch && (i < arr.size - 1 || s.size > 1)) || 
       (a.last[-1] == join_ch && (i > 1 || a.last.size > 1)) 
      a.last << " #{s}"
    else
      a << s
    end
  end
end

join_some ["a", "&", "b", "d"]      #=> ["a & b", "d"]
join_some ["a", "& b", "c"]         #=> ["a & b", "c"]
join_some ["&", "b", "c"]           #=> ["&", "b", "c"]
join_some ["a", "b", "&"]           #=> ["a", "b", "&"]
join_some ["a", "&", "b", "&", "c"] #=> ["a & b & c"]
join_some ["a", "& b &", "c"]       #=> ["a & b & c"]
join_some ["&", "& b", "c"]         #=> ["& & b", "c"]
join_some [" &", "b", "c"]          #=> [" & b", "c"]
join_some ["&", "&", "&"]           #=> ["& & &"]
join_some ["a", "+ b", "+ c"], "+"  #=> ["a + b + c"]
对于上述10个示例,该方法给出的结果与第一种方法相同。下面以自由间距模式表示正则表达式,并附有解释性注释。这里
join#ch=>“&”
split#ch=>\x00

r = /
    (?<=            # begin positive lookbehind
      \A            # match the beginning of the string
      .             # match any char
      |             # or
      [^#{join_ch}] # match any char other than the join char
    )               # end positive lookbehind
    #{split_ch}     # match split char
    (?=             # begin a positive lookahead
      [^#{join_ch}] # match any char other than the join char
      |             # or
      .             # match any char
      \z            # match end of the string
    )               # end positive lookahead
    /x              # free-spacing regex definition mode
  #=> (?<=          # begin positive lookbehind
  #     \A          # match the beginning of the string
  #     .           # match any char
  #     |           # or
  #     [^&]        # match any char other than the join char
  #   )             # end positive lookbehind
  #   \x00          # match split char
  #   (?=           # begin a positive lookahead
  #     [^&]        # match any char other than the join char
  #     |           # or
  #     .           # match any char
  #     \z          # match end of the string
  #   )             # end positive lookahead
  #   /x            # free-spacing regex definition mode
r=/

(?(我的解决方案不使用特殊字符,在我看来,最不令人惊讶的是,它

  • 忽略字符串开头或结尾的额外尾随(&s)
  • 单独保留连续的(分开的)&s(可能需要在它们之间插入某些内容)
  • 与&&、&&&、&hello&、
代码:


当您的第二个项目以
&
开头时,您为什么要使用
end\u with?
?只需一个指针即可:假设您希望这两个元素
[“a”、“&b”]
最终成为元素
“a&b”
(即具有额外的空间)您还需要能够修改元素。因此,仅使用
chunk\u而
是无法实现这一点的。也许可以尝试编写一些伪代码来描述这应该如何工作,然后用Ruby编写它,一旦您有了可以工作的东西,您就可以要求提供使其更地道的技巧了。那么
['a'、'&b&'、'c']
['a'、'&b'、'&c']
?、、、
['a'、'&','b'、'&','c']