Ruby-реализация алгоритма Саундэкс


Я новичок в Ruby. Я обычно слинг кода на C#. Что я могу сделать, чтобы сделать этот простой класс Саундэкс более Rubyesque?

class Surname
  attr_accessor :value

  def initialize(input)
    @value = input
  end

  def soundex
    result = ''
    @value.chars.drop(1).each do |s|
      number = soundex_value(s).to_s
      result << number unless result[-1,1] == number
    end
    @value.chars.first << result.ljust(3,'0')
  end

  def soundex_value(s)
    case s
    when /[bfpv]/
      1
    when /[cgjkqsxz]/ 
      2
    when /[dt]/ 
      3
    when /l/ 
      4
    when /[mn]/ 
      5
    when /r/ 
      6
    else ''
    end
  end
end

def print_name(input)
  surname = Surname.new(input)
  puts(surname.value + ' => ' + surname.soundex)
end

['Smith', 'Johnson', 'Williams', 'Jones', 'Brown'].each do |s|
  print_name s
end

Вывод:

Смит => Серии S530
Джонсон => J525
Уильямс => W452
Джонс => J520
Коричневый => B650


963
5
задан 29 октября 2011 в 08:10 Источник Поделиться
Комментарии
2 ответа

Согласно вашему запросу, ваш код превращается в Рубиновый путь, возможно, будет выглядеть следующим образом.

Небольшой момент: в нашей продукции, в Руби мире, мы могли бы избежать => жирная запятая , которая рубистов (по крайней мере в англоязычном мире) называют хэш-ракета, потому что:


  • Он читает как Руби (старшего) хэш связи c синтаксис.

  • В Ruby язык документации (см., например, массива), подобные #=>, содержащий хэш-ввести комментарий и хэш-ракета (предположительно, это дало нам имя), показывает нам результат (или ценности) отдельные строки кода—два значения конфликта.

Кстати, мы также хотели избежать ->, тире-больше, что в Руби (синтаксис) производит лямбда.

class Soundex < String
IGNORED_BEGINNING_LENGTH = 1
MINIMUM_LENGTH = 3

CASES = [ # Keep order.
/[bfpv]/,
/[cgjkqsxz]/,
/[dt]/,
/l/,
/[mn]/,
/r/,
]
CASES_LENGTH = CASES.length

def initialize(surname)
a = surname.split ''
kept = a.take(IGNORED_BEGINNING_LENGTH).join ''
indices = a.drop(IGNORED_BEGINNING_LENGTH).map do |e|
(0...CASES_LENGTH).detect{|i| e =~ (CASES.at i)}
end.compact
# Adjust to one-based notation; collapse repetition; right-pad with zeros.
digits = indices.map(&:succ).join('').squeeze.ljust MINIMUM_LENGTH, '0'
super kept + digits
end

def self.show(s) "#{s}: #{new s}" end
end

names = %w[Smith Johnson Williams Jones Brown Atchison]
names.each{|s| puts Soundex.show s}

дает результаты


Смит: Серии S530
Джонсон: J525
Уильямс: W452
Джонс: J520
Браун: B650
Атчисон: A325

3
ответ дан 22 января 2012 в 01:01 Источник Поделиться

Во-первых: установка RSpec и написать несколько тестов, если вы еще этого не сделали. Что будет убедиться, что вы ничего не сломать во время рефакторинга. (И тогда вообще все тест-сначала развитие, если у вас уже нет.) Кроме того, существуют реализации Ruby функция Soundex. Вы, возможно, захотите использовать один вместо того, чтобы писать свои собственные.

Для остальных это:


  • Я думаю, что ваша реализация-это неправильно! Попробуйте это: а "Атчисон" выход "A322"? Надо.

  • Зачем вам нужен отдельный класс для фамилия? Возможно, имеет смысл иметь модуль с функцией Soundex-алгоритм, который либо смешивается в строки по мере необходимости или вызов метода с функцией синтаксиса (например, функция Soundex::кодировать фамилия). Я не уверен.

  • Если вам не нужен отдельный класс для фамилия, возможно, следует расширить строку, или делегировать его строковый элемент, так что вы можете легко позвонить string методы на нем. Но я думаю, что старые строки с включенными модуль будет работать лучше.

  • @значению похоже на имя сделаем. Возможно, @имя или что?

  • Вам может и не понадобится attr_accessor, с @фамилия.to_s было бы более идиоматические, чем @фамилия.значение.

  • Вместо этого новое значение.чарс.капли(1).каждый блок, вы можете использовать карту.

  • Регулярные выражения не может быть правильно для случая выражение; Вы можете , Когда 'б', 'р' вместо этого. Или вы можете вложить в дело целиком и есть хэш: {'Б' => 1, 'с' => 2, 'Д' => 3, 'Ф' => 1, ... }. Или мне кажется, что массив#ассоциация может быть полезна здесь...

  • Поскольку вы звоните to_s на soundex_value единственный раз, когда вы используете его, может быть, она должна просто возвращать строку в первую очередь.

Удачи! Я надеюсь, что эти предложения окажутся полезными.

1
ответ дан 1 ноября 2011 в 03:11 Источник Поделиться