使用不同分隔符连接值数组的功能方法?

时间:2011-10-26 12:21:08

标签: ruby

我正在寻找一种功能性的方法来执行这种凌乱的程序逻辑:

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的东西,所以你可能无论如何都不能运行它,抱歉:(

6 个答案:

答案 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