Тернарный оператор - PullRequest
       2

Тернарный оператор

1 голос
/ 01 июля 2011

У меня есть массив d = ['foo', 'bar', 'baz'], и я хочу собрать его элементы в строку, ограниченную , и and в последнем элементе, чтобы он стал foo, bar and baz.

Вот что я пытаюсь сделать:

s = ''
d.each_with_index { |x,i|
  s << x
  s << i < d.length - 1? i == d.length - 2 ? ' and ' : ', ' : ''
}

, но интерпретатор выдает ошибку:

`<': comparison of String with 2 failed (ArgumentError)

Однако это работаетс += вместо <<, но Ruby Cookbook говорит, что:

Если для вас важна эффективность, не создавайте новую строку, когда вы можете добавлять элементы в существующую строку.[И так далее] ... Вместо этого используйте str << var1 << ' ' << var2.

Возможно ли в этом случае без +=?

Кроме того, должен быть более элегантный способ сделать это, чем приведенный выше код.

Ответы [ 3 ]

5 голосов
/ 01 июля 2011

Вам просто не хватает скобок:

    d = ['foo', 'bar', 'baz']
    s = ''
    d.each_with_index { |x,i|
      s << x
      s << (i < d.length - 1? (i == d.length - 2 ? ' and ' : ', ') : '')
    }
4 голосов
/ 01 июля 2011

Я бы нашел

s << i < d.length - 1? i == d.length - 2 ? ' and ' : ', ' : ''

трудно читать или поддерживать.

Я бы, наверное, изменил на

join = case
when i < d.length - 2 then ", "
when i == d.length - 2 then " and "
when i == d.length then ""
end
s << join

Или, возможно, сделать

earlier_elements = d[0..-2].join(", ")
s = [earlier_elements, d[-1..-1]].join(" and ")

Или

joins = [", "] * (d.length - 2) + [" and "]
s = d.zip(joins).map(&:join).join
1 голос
/ 02 июля 2011

Намного проще, как это:

"#{d[0...-1].join(", ")} and #{d.last}"
...