2010-01-22 1 views
7

Я программист на Java/C++, а Ruby - мой первый язык сценариев. Иногда я нахожу, что я не использую его так продуктивно, как мог, в некоторых областях, например, таких как:Быстрый совет: как это должно быть написано в Ruby?

Цель: анализировать только определенные строки из файла. Образец, который я собираюсь сделать, состоит в том, что есть одна очень большая линия с размером больше 15, остальные, безусловно, меньше. Я хочу игнорировать все строки до (и в том числе) большого.

def do_something(str) 
    puts str 
end 


str = 
'ignore me 
me too! 
LARGE LINE ahahahahha its a line! 
target1 
target2 
target3' 

flag1 = nil 
str.each_line do |line| 
    do_something(line) if flag1 
    flag1 = 1 if line.size > 15 
end 

Я написал это, но я думаю, что это могло быть написано намного лучше, то есть, должно быть лучше, чем установка флага. Также приветствуются рекомендации о том, как писать красивые строки Ruby.

Примечание/Уточнение: Мне нужно напечатать ВСЕ строки ПОСЛЕ первого появления БОЛЬШОЙ ЛИНИИ.

+0

Можете ли вы определить «лучше», что ваш цикл do делает именно то, что вы хотите, всего в нескольких строках кода, и его очень легко читать и понимать намерение. – Beanish

+0

Лучше не по производительности, а по лучшему. Приведенные до сих пор примеры - это то, что я ищу (в основном, если бы только люди лучше перечитали разъяснение). – Zombies

ответ

10
str.lines.drop_while {|l| l.length < 15 }.drop(1).each {|l| do_something(l) } 

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

Split строка в строках и падение линии короче 15 символов. Затем отбросьте еще одну строку (т. Е. Первую с более чем 14 символами). Затем сделайте что-нибудь с каждой оставшейся линией.

Вам даже не нужно обязательно понимать Ruby или программировать на всех, чтобы проверить, правильно ли это.

+0

Вы можете избавиться от лишнего падения, если вы измените условие на <=. Никогда не знал о drop_while. Благодаря! – Farrel

+0

@Farrel: Нет, вы не можете. Если длинная строка имеет более 15 символов, она будет действовать точно так же, как и раньше. Если он имеет ровно 15 символов, он просто удалит всю строку. – sepp2k

+0

Farrel: Если длинная строка длиннее 15 символов (как в примере), вам все равно потребуется дополнительное падение. Кроме того, я должен согласиться, что drop_while довольно аккуратно. – abeger

3
require 'enumerator' # Not needed in Ruby 1.9 

str.each_line.inject(false) do |flag, line| 
    do_something(line) if flag 
    flag || line.size > 15 
end 
1
lines = str.split($/) 
start_index = 1 + lines.find_index {|l| l.size > 15 } 
lines[start_index..-1].each do |l| 
    do_something(l) 
end 
+0

делает это в 1.8.6? Я получаю undefined метод 'lines' error – Zombies

+0

Нет, строки новые в 1.8.7. Я обновлю ответ на использование split. – mckeed

+0

В 1.8.6 строки уже считаются массивом строк, поэтому вам это не нужно. В 1.9, однако, строки считаются массивом строк, символов, байтов или кодовых точек, поэтому вы должны явно указать, какое поведение вы хотите. –

Смежные вопросы