Functional approach to join a series of values ​​with variable separator?

advertisements

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