Объявление целочисленного диапазона с шагом! = 1 в рубине - PullRequest
14 голосов
/ 12 июня 2010

ОБНОВЛЕНИЕ 2 : Для потомков, вот как я решил сделать это (благодаря вкладу Йорга):

100.step(2, -2) do |x|
    # my code
end

(Очевидно, что есть много способов сделать это; но, похоже, это самый "рубиновый" способ сделать это, и это именно то, чего я добился.)


ОБНОВЛЕНИЕ : ОК, поэтому я искал step:

(2..100).step(2) do |x|
    # my code
end

Но оказывается, что я не был на 100% откровенен в своем первоначальном вопросе. Я на самом деле хочу перебрать этот диапазон в обратном направлении. К моему удивлению, отрицательный шаг не является законным.

(100..2).step(-2) do |x|
    # ArgumentError: step can't be negative
end

Итак: как мне сделать это задом наперед?


Привет, ребята, я совершенно новый для Руби, так что будьте осторожны.

Скажем, я хочу перебрать диапазон четных чисел от 2 до 100; как бы я это сделал?

Очевидно, я мог бы сделать:

(2..100).each do |x|
    if x % 2 == 0
        # my code
    end
end

Но, очевидно (снова), это было бы довольно глупо.

Я знаю, что мог бы сделать что-то вроде:

i = 2
while i <= 100
    # my code
    i += 2
end

Полагаю, я мог бы написать свой собственный класс, предоставляющий собственный метод each (?). Я почти уверен, что это будет излишним.

Меня интересуют две вещи:

  1. Возможно ли сделать это с некоторым изменением стандартного синтаксиса Range (т.е. (x..y).each)?
  2. В любом случае, каков был бы самый идиоматический «Рубиновый способ» для достижения этой цели (используя Range или иначе)? Как я уже сказал, я новичок в языке; поэтому любые рекомендации, которые вы можете предложить о том, как делать вещи в более типичном стиле Ruby, будут очень благодарны.

Ответы [ 3 ]

23 голосов
/ 13 июня 2010

Вы не можете объявить Range с "шагом". У диапазонов нет шагов, у них просто есть начало и конец.

Вы, конечно, можете повторять по Range шагами, например, так:

(2..100).step(2).reverse_each(&method(:p))

Но если все, что вам нужно, это итерация, то для чего вам нужен Range для начала? Почему бы просто не повторить?

100.step(2, -2, &method(:p))

Это дает дополнительное преимущество: в отличие от reverse_each ему не нужно создавать промежуточный массив.

3 голосов
/ 12 июня 2010

Этот вопрос отвечает на ваш вопрос: о диапазоне рубинов?

(2..100).step(2) do |x|
    # your code
end
1 голос
/ 04 марта 2012

У меня была похожая проблема, вот несколько способов, которые я нашел, чтобы сделать то же самое ПРОСТОЕ, что я использовал шаг в конце, потому что это допускало ОТРИЦАТЕЛЬНЫЕ и ДРАГОЦЕННЫЕ приращения, и у меня не было условий, кроме границ для поиска

  case loop_type

    when FOR
      # doen't appear to have a negative or larger than 1 step size!
      for kg in 50..120 do
        kg_to_stones_lbs(kg)
      end

    when STEP
      120.step(70,-0.5){ |kg|
        kg_to_stones_lbs(kg)
      }

    when UPTO
      50.upto(120) { |kg|
        kg_to_stones_lbs(kg)
      }

    when DOWNTO
      120.downto(50){ |kg|
        kg_to_stones_lbs(kg)
      }

    when RANGE
      (50..120).reverse_each{ |kg|
        kg_to_stones_lbs(kg)
      }

    when WHILE
      kg = 120
      while kg >= 50
        kg_to_stones_lbs(kg)
        kg -= 0.5
      end
  end

O / P:

92,0 кг - 14 фунтов 7

91,5 кг - 14 фунтов 6

91,0 кг - 14 фунтов 5

90,5 кг - 14 фунтов 401

90,0 кг - 14 фунтов 2

89,5 кг - 14 фунтов 1

89,0 кг - 14 фунтов 0 1018 *

88,5 кг - 13 13 фунтов

88,0 кг - 13 фунтов 1222 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...