2016-10-12 3 views
6

Можно ли использовать деструктурирование в рубине, чтобы извлечь конец и начать с диапазона?Как разрушить диапазон в Ruby?

module PriceHelper 
    def price_range_human(range) 
    "$%s to $%s" % [range.begin, range.end].map(:number_to_currency) 
    end 
end 

Я знаю, что я могу использовать массив принуждение как очень плохой хак:

first, *center, last = *rng 
"$%s to $%s" % [first, last].map(:number_to_currency) 

Но есть синтаксический способ получить begin и end без фактического создания массива вручную?

min, max = (1..10) 

Было бы замечательно.

+2

Вам нужно либо укажите, что вас беспокоит только двухточечные диапазоны, или уточните, хотите ли вы 'max' или' last', которые вы, кажется, используете взаимозаменяемость. –

ответ

2

No, До тех пор, пока я не ошибаюсь Кэри Swoveland, еженедельные новости мира или другой таблоид, я буду продолжать верить без каких-либо доказательств того, что ответ «нет»; но это достаточно легко сделать.

module RangeWithBounds 
    refine Range do 
    def bounds 
     [self.begin, self.end] 
    end 
    end 
end 

module Test 
    using RangeWithBounds 
    r = (1..10) 
    b, e = *r.bounds 
    puts "#{b}..#{e}" 
end 

Затем снова, я бы просто написать "#{r.begin.number_to_currency}..#{r.end.number_to_currency}" в первую очередь.

+0

Не '' r'coerce диапазон в массив? – max

+1

@max: Нет, '* r.bounds' является' * (r.bounds) ', а не' (* r) .bounds'. Помните, что '*' не является оператором, а синтаксической конструкцией в присваивании lvalue, присваивании rvalue, списке аргументов (как определении, так и вызове) и литералах массива. У него даже нет приоритета, потому что он не может быть оценен «внутри» выражения. – Amadan

+0

Спасибо, я думаю, это имеет больше смысла. Я никогда не думал, что вы не можете делать 'array. *', Как вы можете, с операторами. – max

4

Начало и конец? Я бы воспользовался:

foo = 1..2 
foo.min # => 1 
foo.max # => 2 

Попытка использовать деструктурирование для диапазона - плохая идея. Представьте размеры массива, который может быть сгенерирован, затем выброшен, теряя время и память процессора. На самом деле это отличный способ для DOS вашего собственного кода, если ваш диапазон заканчивается Float::INFINITY.


end не то же самое, как max: в 1 ... 10, end 10, но max является 9

Это потому, что start_val ... end_val эквивалентно start_val .. (end_val - 1):

start_value = 1 
end_value = 2 

foo = start_value...end_value 
foo.end # => 2 
foo.max # => 1 

foo = start_value..(end_value - 1) 
foo.end # => 1 
foo.max # => 1 

max отражает реальность значений, фактически используемых Ruby, когда итерации по диапазону или тестирования для включения в диапазон.

По моему мнению, end должен отражать фактическое максимальное значение, которое будет учитываться внутри диапазона, а не значение, используемое в конце определения диапазона, но я сомневаюсь, что это изменится, иначе это повлияет на существующие код.

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

+0

'Range # min' и' max' - это не то же самое, что 'end' и' begin'. 'max' фактически преобразует массив в диапазон и получает последний элемент afaik. – max

+0

Его в основном потому, что '# max' можно назвать' max (n) {| a, b | block} → obj'. – max

+0

'min' и' max' возвращают начало и конец диапазона. В документации нет ничего о том, что оно преобразуется в массив. Если это было, преобразование '1..Float :: INFINITY' при использовании' max' никогда не вернется. Они в основном такие же, как 'begin' и' end', за исключением того, что они позволяют использовать блок. 'begin 'и' end' должны быть быстрее, хотя, глядя на источник. –

0

Ответ Амадана в порядке.Вам просто нужно удалить восклицательный знак (*) при его использовании, так как не требуется

например,

 
> "%s to %s" % (1..3).bounds.map{|x| number_to_currency(x)} 
=> "$1.00 to $3.00" 
1

Вы можете использовать minmax для destructure ваш простой выбор:

min, max = (1..10).minmax 
min # => 1 
max # => 10 
+2

Помните, что это возвращает минимальное и максимальное значение диапазона, а не начало и конец диапазона. – Stefan