Может ли использование рубинового триггера в качестве фильтра быть менее хитрым? - PullRequest
3 голосов
/ 21 февраля 2011

Чтобы получить часть текста, я использую true if kludge перед триггером:

desired_portion_lines = text.each_line.find_all do |line|
  true if line =~ /start_regex/ .. line =~ /finish_regex/
end
desired_portion = desired_portion_lines.join

Если я удаляю бит true if, он жалуется

плохое значение для диапазона (ArgumentError)

Можно ли сделать его менее хитрым, или я должен просто сделать

desired_portion_lines = ""
text.each_line do |line|
  desired_portion_lines << line if line =~ /start_regex/ .. line =~ /finish_regex/
end

Или естьлучший подход, который не использует перечисление?

Ответы [ 3 ]

1 голос
/ 21 февраля 2011

Я думаю

desired_portion_lines = ""
text.each_line do |line|
  desired_portion_lines << line if line =~ /start_regex/ .. line =~ /finish_regex/
end

вполне приемлемо. Оператор .. очень мощный, но не используется многими людьми, вероятно потому, что они не понимают, что он делает. Возможно, это выглядит странно или неловко для вас, потому что вы не привыкли его использовать, но оно будет расти на вас. Это очень часто встречается в Perl, когда имеешь дело с диапазонами строк в текстовых файлах, где я впервые столкнулся с этим и в конце концов использовал его очень часто.

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

desired_portion_lines = ""
text.each_line do |line|
  desired_portion_lines << line if ( (line =~ /start_regex/) .. (line =~ /finish_regex/) )
end

Ruby (и Perl) кодеры, похоже, не любят использовать круглые скобки, но я считаю, что они полезны для визуального разделения логических тестов. Для меня это удобочитаемость и, как следствие, необходимость в обслуживании.

Единственное, что я могу подумать о том, что может помочь, это изменить desired_portion_lines на массив и вставить в него выбранные строки. В настоящее время использование desired_portion_lines << line добавляет к строке, каждый раз изменяя ее. Возможно, быстрее будет нажать на массив, а затем соединить его элементы для построения вашей строки.

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

desired_portion = text.each_line.find_all { |line| line =~ /start_regex/ .. line =~ /finish_regex/ }.join

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

1 голос
/ 21 февраля 2011

, если вы делаете это построчно, мои предпочтения примерно такие:

line =~ /finish_regex/ && p=0
line =~ /start_regex/ && p=1
puts line if p

если у вас все в одной строке. Я бы использовал split

mystring.split(/finish_regex/).each do |item|
  if item[/start_regex/] 
     puts item.split(/start_regex/)[-1]
  end
end
0 голосов
/ 12 марта 2015

Вы можете сохранить три символа, заменив true if на !!() (с триггером в скобках).

...