Предположим, например, что мы хотим игнорировать английские артикли a, an и the, если они встречаются в начале строки, а также не обращать внимания на большинство знаков препинания. Для этого следует переопределить встроенный метод <=> (он вызывается из методов <, <=, > и >=). В листинге 2.1 показано, как это сделать.

Листинг 2.1. Специализированное сравнение строк

class String

 alias old_compare <=>

 def <=>(other)

  a = self.dup

  b = other.dup

  # Удалить знаки препинания.

  a.gsub!(/[,.?!:;]/, '')

  b.gsub!(/[,.?!:;]/, '')

  # Удалить артикли из начала строки.

  a.gsub!(/^(a |an | the )/i, '')

  b.gsub!(/^(a |an | the )/i, '')

  # Удалить начальные и хвостовые пробелы.

  a.strip!

  b.strip!

  # Вызвать старый метод <=>.

  # a.old_compare(b)

 end

end

title1 = 'Calling All Cars'

title2 = 'The Call of the Wild'

# При стандартном сравнении было бы напечатано 'yes'.

if title1 < title2

 puts 'yes'

else

 puts 'no' # А теперь печатается 'no'.

end

Обратите внимание, что мы «сохранили» старый метод <=> с помощью ключевого слова alias и в конце вызвали его. Если бы мы вместо этого воспользовались методом <, то был бы вызван новый метод <=>, что привело бы к бесконечной рекурсии и в конечном счете к аварийному завершению программы.

Отметим также, что оператор == не вызывает метод <=> (принадлежащий классу-примеси Comparable). Это означает, что для специализированной проверки строк на равенство пришлось бы отдельно переопределить метод ==. Но в рассмотренном случае в этом нет необходимости.

Допустим, что мы хотим сравнивать строки без учета регистра. Для этого есть встроенный метод casecmp; надо лишь добиться, чтобы он вызывался при сравнении. Вот как это можно сделать:

class String

 def <=>(other)

  casecmp(other)

 end

end

Есть и более простой способ:

class String

 alias <=> casecmp(other)

end

Но это не все. Надо еще переопределить оператор ==, чтобы он вел себя точно так же:

class String

 def ==(other)

  casecmp(other) == 0

 end

end

Теперь все строки будут сравниваться без учета регистра. И при всех операциях сортировки, которые определены в терминах метода <=>, регистр тоже не будет учитываться.

2.8. Разбиение строки на лексемы

Метод split разбивает строку на части и возвращает массив лексем. Ему передаются два параметра: разделитель и максимальное число полей (целое).

По умолчанию разделителем является пробел, а точнее, значение специальной переменной $; или ее англоязычного эквивалента $FIELD_SEPARATOR. Если же первым параметром задана некоторая строка, то она и будет использоваться в качестве разделителя лексем.

s1 = 'Была темная грозовая ночь.'

words = s1.split      # ['Была', 'темная', 'грозовая', 'ночь]

s2 = 'яблоки, груши, персики'

list = s2.split(', ') # ['яблоки', 'груши', 'персики']

s3 = 'львы и тигры и медведи'

zoo = s3.split(/ и /) # ['львы', 'тигры', 'медведи']

Второй параметр ограничивает число возвращаемых полей, при этом действуют следующие правила:

1. Если параметр опущен, то пустые поля в конце отбрасываются.

2. Если параметр — положительное число, то будет возвращено не более указанного числа полей (если необходимо, весь «хвост» строки помещается в последнее поле). Пустые поля в конце сохраняются.

3. Если параметр — отрицательное число, то количество возвращаемых полей не ограничено, а пустые поля в конце сохраняются.

Ниже приведены примеры:

str = 'alpha,beta,gamma,,'

list1 = str.split(',')    # ['alpha','beta','gamma']

list2 = str.split(',',2)  # ['alpha', 'beta,gamma,,']

list3 = str.split(',',4)  # ['alpha', 'beta', 'gamma', ',']

list4 = str.split(',',8)  # ['alpha', 'beta', 'gamma', '', '')

list5 = str.split(',',-1) # ['alpha', 'beta', 'gamma', '', '']

Для сопоставления строки с регулярным выражением или с другой строкой служит метод scan:

str = 'I am a leaf on the wind...'

# Строка интерпретируется буквально, а не как регулярное выражение.

arr = str.scan('а') # ['а','а','а']

# При сопоставлении с регулярным выражением возвращаются все соответствия.

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату