Ruby: следующие / предыдущие значения в массиве, массив петель, позиция массива - PullRequest
5 голосов
/ 28 марта 2011

Допустим, у меня есть массив случайных чисел в произвольном порядке. Допустим, это ID # для людей, которые участвовали в марафоне, и они добавляются в массив в том порядке, в котором они заканчивают, что-то вроде:

race1 = [8, 102, 67, 58, 91, 16, 27]
race2 = [51, 31, 7, 15, 99, 58, 22]

Это упрощенный и несколько надуманный пример, но я думаю, что он передает основную идею.

Теперь пара вопросов:

Во-первых, как я могу получить идентификаторы до и после определенной записи? Допустим, я смотрю на бегуна 58 и хочу знать, кто финишировал до и после него.

race1, runner58: previous finisher=67, next finisher=91
race2, runner58: previous finisher=99, next finisher=22

Во-вторых, если я смотрю на человека, который закончил первым или последним, как я могу вернуть цикл «следующий» или «предыдущий» обратно вокруг массива?

race1, runner8: previous finisher=27, next finisher=102
race2, runner22: previous finisher=58, next finisher=51

Наконец, я хотел бы показать, в какой позиции занял каждый бегун. Учитывая только массив и значение в нем, как я могу узнать, какая «порядковая» позиция в массиве? То есть:

race1: runner8=1st, runner102=2nd, runner67=3rd ... runner27=last

Большое спасибо!

Ответы [ 5 ]

7 голосов
/ 29 марта 2011

Первое и второе:

index = race1.find_index(58)
if !index.nil?
  puts "#{race1[index-1], #{race1[index+1] || race1[0]}"
end

И наконец:

gem install linguistics

тогда

require 'linguistics'
Linguistics::use( :en )
race1.each_with_index {|runner, i| puts "runner#{runner}=#{(i+1).en.ordinal}"}
5 голосов
/ 29 марта 2011

Для элементов # 1 и # 2 я бы создал метод, который возвращает предыдущий и следующий элементы по id, автоматически оборачивая для первого и последнего, например:

class Array
  def prev_next(id)
    idx = self.index(id)
    raise Error.new("no racer with id #{id}") unless idx
    [self[idx-1], self[(idx+1)%self.size]]
  end
end
race1.prev_next(58) # => [67, 91]
race1.prev_next(8) # => [27, 102]

Обратите внимание, что единственный возможный отрицательныйindex, -1, фактически сворачивается до конца благодаря Ruby's array.slice и, используя модуль размера массива, мы можем отрегулировать для переноса до конца.Для третьего элемента ординализация может быть сделана так:

class Integer
  def ordinalize
    s = self.to_s
    case s
      when /1[123]$/ then s + 'th'
      when /1$/ then s + 'st'
      when /2$/ then s + 'nd'
      when /3$/ then s + 'rd'
      else s + 'th'
    end
  end
end
race1.each_with_index {|x,i| puts "runner#{x}=#{(i+1).ordinalize}"}
# runner8=1st
# runner102=2nd
# runner67=3rd
# ...
2 голосов
/ 29 марта 2011

Метод find_index, вероятно, будет лучшим выбором здесь.

runner_index = race.find_index finisher_number #find the index of the racer
previous_runner = race[runner_index - 1] #a negative index will wrap around
next_runner = race[runner_index + 1] || race[0] #use a null guard to wrap to the front
0 голосов
/ 26 марта 2015

Первый и Второй:

race1.rotate(race1.index(58) + 1).first # next
race1.rotate(race1.index(58) - 1).first # previous

Кредит: видел это на этом посте: http://jamonholmgren.com/rubymotion-react-pattern/

0 голосов
/ 28 марта 2011

Здравствуйте, я не знаю точно, что вы хотите сделать, но если вы используете ruby ​​1.9, вы должны взглянуть на метод rotate, а если вы используете ruby ​​1.8.7, вы должны попытаться построить что-то вокруг метода index как

race1[race1.index(58) +1] will give 98 (the next one)
race1[race1.index(58) -1] will give 67 (the previous one)

Вам нужно немного подправить, чтобы имитировать поворот (путем проверки значения возвращенного индекса по сравнению с размером массива или 0)

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