I'm looking for a functional way to perform this messy procedural logic:
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
I basically have an array of objects (all the same type) and need to join their #name
attributes, but following an object that has a particular characteristic, I need a different separator.
This is an easily solved problem, but I'm looking for the cleanest, most functional approach. I first dived into #inject
, but you lose the previous value at each iteration, so I couldn't make that work. Any ideas?
I'd love to post the real code instead of pseudo code, but it's really dense and complex DataMapper Relationship stuff, so you probably couldn't just run it anyway, sorry :(
If I understand correctly what you want, this should work:
output = values.map do |v|
["/" + v.name.to_s, v.special? ? "/x" : ""]
end.flatten[0...-1].join
Alternative phrasing (Ruby 1.9):
output = "/" + values.flat_map do |v|
[v.name.to_s, ("x" if v.special?)]
end.take(2*values.size - 1).join("/")
Without analyzing the algorithm, just making it functional:
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