这是Ruby 2.4。我有一个字符串数组,如果它们以特殊字符开头或结尾,我想融合连续元素。所以,例如,如果我的特殊角色是“&”我有一个数组
["a &", "b", "c", "d"]
我希望结果是
["a & b", "c", "d"]
同样,如果数组是
["a", "&", "b", "c"]
我希望结果是
["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”之间的空格)。我是否可以对上述内容进行调整以使其按预期工作?
答案 0 :(得分:1)
这有两种方法可以做到这一点。我假设,在示例中,没有数组的元素(字符串)以空格开头或结尾。
<强>#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"]
我不确定前几个例子的返回值是否符合要求。
<强>#2 强>
第一步是join(c)
数组的所有元素形成一个单独的字符串,其中c
是一个字符,不存在于数组的任何元素中。 (我选择使用0.chr #=> x00
。)然后我们可以根据需要使用正则表达式r
来split(r)
字符串。
def join_some(arr, join_ch='&')
split_ch = 0.chr
r = /(?<=\A.|[^#{join_ch}])#{split_ch}(?=[^#{join_ch}]|.\z)/
arr.join(split_ch).split(r).map { |s| s.tr(split_ch, ' ') }
end
该方法给出与上面给出的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
答案 1 :(得分:0)
这很啰嗦,但通过了测试。该方法采用数组和特殊字符作为参数。最初的join.split.reject.map
'将数组标准化为剥离的单个元素,除了两边都有空格的特殊字符。然后我们两次申请Enumerable#chunk_while
。
def chunky arr, char
char = "\\".concat char
arr.join(' ')
.split(/(\w)/)
.reject { |s| s.strip.empty? }
.map { |e| e.match?(' &') ? ' & ': e }
.chunk_while { |a,b| a.match?(/\s#{char}\s/) && b.match?(/\w/) }
.map(&:join)
.chunk_while { |a,b| a.match?(/\w/) && b.match?(/\s#{char}\s\w/) }
.map { |s| s.join.strip }
end
p chunky ["a &", "b", "c", "d"], '&'
#=> ["a & b", "c", "d"]
p chunky ["a", "-", "b", "c"], '-'
#=> ["a - b", "c"]
p chunky ["a", "+ b", "c"], '+'
#=> ["a + b", "c"]
p chunky ["*", "b", "c"], '*'
#=> ["*", "b", "c"]
p chunky ["a", "b", "&"], '&'
#=> ["a", "b", "&"]
p chunky ["a", "b", "& c"], '&'
#=> ["a", "b & c"]
答案 2 :(得分:0)
我的解决方案并没有使用特殊字符,在我看来,这是最不令人惊讶的,它
代码:
-(void)tapDetected{
HomeMainViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier: @ "homeVC"];
[self.navigationController pushViewController:vc animated: YES];
}
结果:
def join_strings array, s = '&'
array = array.flat_map {|i| i.match(Regexp.new"(?:^ *(?:\\#{s} )*(\\#{s})(?:\\#{s} )* *$)|(?:^ *(?:(\\#{s}) )*(.*?)(?: (\\#{s}))* *$)")[1..4]} - [nil]
i = 0
while i < array.length - 2
if array[i..i+2].map {|i| i == s} == [false, true, false]
array[i] = array[i..i+2].join ' '
array.slice!(i + 1, 2)
else i += 1 end
end
array
end