Как я могу заказать список букв ("a", "b", "c", ..., "z", "aa", "ab")? Строка # succ и <=>, похоже, не очень хорошо играют вместе в этом случае - PullRequest
2 голосов
/ 05 января 2011

Один из моих объектов ('item') имеет идентификатор ('letter_id') в формате "a", "b", ..., "aa", "ab" и т. Д. Чтобы сгенерировать его, яЯ использую Ruby's String#succ в методе экземпляра, подобном этому:

def set_letter_id
  last = parent.items.all(:order => "letter_id ASC").last
  if last.nil?
    self.letter_id = 'a'
  else
    self.letter_id = last.letter_id.succ
  end
end

Теперь это прекрасно работает до 28-й буквы.27-е будет правильно генерировать « aa », но тогда значение last всегда будет возвращать элемент с буквой_идуса « z », потому что порядок возвращаемых элементов не 'я следовал тем же правилам, что и String#succ.

Я узнал об этом из комментария здесь - но сейчас я изо всех сил пытаюсь найти хорошее решение этой проблемы.В основном проблема заключается в следующем:

"aa".succ #=> "ab" - great, that's what I want.
"z"<=>"aa" #=> 1 - not so great, "z" should actually be less than "aa"

Очевидно, что это не обязательно ошибка, но это затрудняет сортировку и упорядочивание списка letter_ids в этом формате.Кто-нибудь сталкивался с этим и нашел обходной путь или какие-либо предложения, которые я мог бы попробовать?Спасибо!

Ответы [ 3 ]

4 голосов
/ 05 января 2011

В ответах по опубликованной вами ссылке было решение - вы должны написать собственный <=> вместо sort_by{|i|[i.length,i]}

irb> %w{a b c z aa ab zz aaa}.shuffle.sort_by { |i| [i.length,i] }
=> ["a", "b", "c", "z", "aa", "ab", "zz", "aaa"]
2 голосов
/ 05 января 2011

Вы можете переопределить метод <=> для своей модели изделия, чтобы сравнить сначала по длине идентификатора, а затем по буквенно-цифровому.

Примерно так:

class Item < ActiveRecord::Base
  # stuff

  def <=>(other)
    len_comp = self.letter_id.length <=> other.letter_id.length
    return len_comp if len_comp != 0
    self.letter_id <=> other.letter_id
  end
end

Таким образом, вы сначала сравниваете меньшую длину идентификатора (т. Е. "z" до "aa"), а затем лексикографически.

1 голос
/ 05 января 2011

Именно из-за такого рода проблем некоторые люди не одобряют использование String#succ.. Это вступает в конфликт с Range, Object#to_a и другими.

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

>> t
=> ["x", "y", "z", "aa", "ab", "ac", "ad", "ae", "af", "ag"]

>> t.shuffle.sort_by { |e| "%3s" % [e] }
=> ["x", "y", "z", "aa", "ab", "ac", "ad", "ae", "af", "ag"]

Вы можете даже перенормировать этот способ и отказаться от sort_by.

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