我正在寻找一种功能性的方法来执行这种凌乱的程序逻辑:
values = [a, b, c, d, e, f]
last_value = nil
string = ""
values.each do |v|
string << if last_value && last_value.special?
"/x/" + v.name.to_s
else
"/" + v.name.to_s
end
last_value = v
end
我基本上有一个对象数组(所有类型相同)并且需要加入它们的#name
属性,但是在一个具有特定特征的对象之后,我需要一个不同的分隔符。
这是一个容易解决的问题,但我正在寻找最干净,最实用的方法。我第一次潜入#inject
,但是你在每次迭代时都失去了之前的值,所以我无法做到这一点。有什么想法吗?
我想发布真实的代码而不是伪代码,但它确实是密集而复杂的DataMapper Relationship的东西,所以你可能无论如何都不能运行它,抱歉:(
答案 0 :(得分:1)
尝试values.collect{|v| v.special? ? v + "/x/" : v + "/"}.join("")
EDIT,使用注入解决方案:
values.inject(["", ""]) {|path_and_sep, item| [path_and_sep[0] + path_and_sep[1] + item, item.special? "/x/" : "/"]} [0]
答案 1 :(得分:1)
在最后进行连接以摆脱前导和尾随/
:
values.collect{|v| v.special? && v != values.last ? [v.name.to_s, "x"] : v.name.to_s}.flatten.join("/")
答案 2 :(得分:1)
如果我理解你想要的东西,这应该有效:
output = values.map do |v|
["/" + v.name.to_s, v.special? ? "/x" : ""]
end.flatten[0...-1].join
替代措辞(Ruby 1.9):
output = "/" + values.flat_map do |v|
[v.name.to_s, ("x" if v.special?)]
end.take(2*values.size - 1).join("/")
不分析算法,只需使其正常运行:
output = ([nil] + values).each_cons(2).map do |last_value, v|
if last_value && last_value.special?
"/x/" + v.name.to_s
else
"/" + v.name.to_s
end
end.join
答案 3 :(得分:1)
我并不是特别自豪,但它有点功能;)
values.clone.unshift(nil).each_cons(2).map { |last_value, v|
last_value.special? ? "/x/" + v.to_s : "/" + v.to_s
}.join()
需要克隆,因为each_cons
会破坏原始数组。
答案 4 :(得分:0)
values.map{|x| x.special? ? [x, SEPARATOR_2] : [x, SEPARATOR_1]}.flatten[0..-2].join('')
答案 5 :(得分:0)
values.inject('') { |m, e| m << e.to_s; m << (e.special? ? '/x/' : '/' }
为了使其完全正常运行,您可以每次重新创建m
而不是附加到它。
为了避免最后一次迭代,也许更复杂的事情如下:
delay = ''
values.inject('') do |m, e|
m << delay << e.to_s
delay = e.special? ? '/x/' : '/'
m
end