Чтение строк из одного файла и добавление в другой файл с суффиксом, чтобы сделать уникальным - PullRequest
1 голос
/ 20 мая 2011

Я обрабатываю документы в ruby.

У меня есть документ. Я извлекаю определенные строки из регулярного выражения и затем добавляю их в другой файл.При добавлении в файл назначения они должны быть сделаны уникальными, поэтому, если эта строка уже существует в файле назначения, я добавляю простой суффикс, например <word>_1.В конце концов я хочу ссылаться на строки по имени, поэтому генерация случайных чисел или строки из даты не годится.

В настоящее время я сохраняю каждое слово, добавленное в массив, а затем каждый раз, добавляя слово, проверяюСтрока не существует в массиве, что хорошо, если есть только 1 дубликат, однако их может быть 2 или более, поэтому мне нужно проверить начальную строку, а затем увеличивать суффикс цикла, пока он не существует (я упростил свойкод, так что могут быть ошибки)

def add_word(word) 
  if @added_words include? word
    suffix = 1
    suffixed_word = word
    while added_words include? suffixed_word
      suffixed_word = word + "_" + suffix.to_s
      suffix += 1
    end
    word = suffixed_word                 
  end
  @added_words << word
end

Это выглядит грязно, есть ли лучший алгоритм или рубиновый способ сделать это?

Ответы [ 4 ]

2 голосов
/ 20 мая 2011

Сделать @added_words набором (не забудьте require 'set'). Это ускоряет поиск, поскольку наборы реализованы с помощью хэшей, при этом все еще используется include? для проверки членства в наборе. Также легко извлечь самый высокий использованный суффикс:

>> s << 'foo' 
#=> #<Set: {"foo"}>
>> s << 'foo_1' 
#=> #<Set: {"foo", "foo_1"}>
>> word = 'foo'
#=> "foo"
>> s.max_by { |w| w =~ /#{word}_?(\d+)?/ ; $1 || '' } 
#=> "foo_1"
>> s << 'foo_12' #=> 
#<Set: {"foo", "foo_1", "foo_12"}>
>> s.max_by { |w| w =~ /#{word}_?(\d+)?/ ; $1 || '' } 
#=> "foo_12"

Теперь, чтобы получить следующее значение, которое вы можете вставить, вы можете просто сделать следующее (представьте, что у вас уже есть 12 foo с, поэтому следующим должно быть foo_13):

>> s << s.max_by { |w| w =~ /#{word}_?(\d+)?/ ; $1 || '' }.next 
#=> #<Set: {"foo", "foo_1", "foo_12", "foo_13"}

Извините, если примеры немного запутаны, у меня сегодня была анестезия. Этого должно быть достаточно, чтобы дать вам представление о том, как наборы могут потенциально помочь вам (хотя большинство из них будет работать и с массивом, но наборы будут быстрее искать).

1 голос
/ 20 мая 2011

Делать это «неправильным путем», но в несколько более хорошем коде:

def add_word(word) 
  if @added_words.include? word
    suffixed_word = 1.upto(1.0/0.0) do |suffix|
      candidate = [word, suffix].join("_")
      break candidate unless @added_words.include?(candidate)
    end
    word = suffixed_word
  end
  @added_words << word
end
1 голос
/ 20 мая 2011

Измените @added_words на Hash с нулевым значением по умолчанию.Тогда вы можете сделать:

@added_words = Hash.new(0)

def add_word( word)
  @added_words[word] += 1
end

# put it to work:

list = %w(test foo bar test bar bar)
names = list.map do |w|
  "#{w}_#{add_word(w)}"
end
p @added_words
#=> {"test"=>2, "foo"=>1, "bar"=>3}
p names
#=>["test_1", "foo_1", "bar_1", "test_2", "bar_2", "bar_3"]
1 голос
/ 20 мая 2011

В этом случае я бы, вероятно, использовал набор или хэш:

#in your class:
require 'set'
require 'forwardable'
extend Forwardable #I'm just including this to keep your previous api

#elsewhere you're setting up your instance_var, it's probably [] at the moment
def initialize
   @added_words = Set.new
end

#then instead of `def add_word(word); @added_words.add(word); end`:
def_delegator :added_words, :add_word, :add 
#or just change whatever loop to use #@added_words.add('word') rather than self#add_word('word')
#@added_words.add('word') does nothing if 'word' already exists in the set.

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

#elsewhere you're setting up your instance_var, it's probably [] at the moment
def initialize
   @added_words = {}
end

def add_word(word, attrs={})
   @added_words[word] ||= []
   @added_words[word].push(attrs)
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...