Руби получает n-й предмет из огромного диапазона - PullRequest
5 голосов
/ 28 апреля 2010

Предположим, у меня есть этот диапазон:

("aaaaa".."zzzzz")

Как бы я мог получить N-й предмет из диапазона, не генерируя всю вещь перед раздачей / каждый раз?

Ответы [ 2 ]

8 голосов
/ 28 апреля 2010

Быстрый и простой способ:

("aaaaa".."zzzzz").first(42).last  # ==> "aaabp"

Если по какой-то причине вам придется делать это снова и снова или если вам нужно избегать построения промежуточного массива для первых N элементов, вы можете написать что-то вроде:

module Enumerable
  def skip(n)
    return to_enum :skip, n unless block_given?
    each_with_index do |item, index|
      yield item unless index < n
    end
    self
  end
end

("aaaaa".."zzzzz").skip(41).first # ==> "aaabp"

Примечание: я предполагаю, что вам нужно решение, которое работает для любого Enumerable, а не для диапазона букв (в этом случае вы должны вычислить его напрямую). Я также предполагаю, что Ruby 1.8.7+, иначе обновление или require "backports"

1 голос
/ 28 апреля 2010

Перечислять только до n,

или

Разработайте функцию, для которой задано число n, f (n) дает вам n-й элемент из вашего диапазона возможных решений.

В вашем случае вы можете рассматривать свой диапазон как систему счисления с базой 26. Перебазировка числа является хорошо известной проблемой. На моем сайте есть пример , чтобы перейти от числа base-10 к числу base-26 (представленному алфавитом) даже в рубине (сделано моим коллегой). Возможно, вам подойдут некоторые варианты этого алгоритма.

Обновление Может быть, это не утонуло в том, что это твой ответ: D

Вот код рубина, чтобы получить n-й предмет вашего диапазона:

def rbase(value)
  a = ('a'..'z')
  b = a.to_a
  base = b.length
  text = []
  begin 
    value, rest = value.divmod(base)
    text << b[rest]
  end until value.zero?
  text.reverse.join
end

тогда вы можете использовать это так.

irb(main):030:0> rbase(789).rjust(10,'a')
=> "aaaaaaabej"
...