2015-01-16 11 views
0

Как получить первое слово из каждой строки? Благодаря помощи от кого-то на переполнение стека, я работаю на код ниже:Извлечь первое слово из строки в файле с помощью Ruby

File.open("pastie.rb", "r") do |file| 
    while (line = file.gets) 
    next if (line[0,1] == " ") 
    labwords = line.split.first 
    print labwords.join(' ') 
    end 
end 

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

+0

Я думаю, что вы могли бы быть смущены о том, что делает 'дальше, если ...' линия. В отличие от обычного выражения 'if', оно завершено только на этой строке, и следующие строки не являются частью этого (что и предлагает ваш отступы). Что касается вашего вопроса: попробуйте вынуть '.join ('')' и посмотреть, что произойдет. – Jon

+0

Вы правы. Я удалил .join, потому что получаю ошибку метода. –

ответ

1

Рассмотрим это:

def first_words_from_file(file_name) 
    lines = File.readlines(file_name).reject(&:empty?) 
    lines.map do |line| 
    line.split.first 
    end 
end 

puts first_words_from_file('pastie.rb') 
+0

'lines = File.open (имя_файла, 'r') {| f | f.readlines} '- настоящий неудобный способ чтения файла в массив. Вместо этого используйте 'File.readlines (имя_файла)'. Он делает то же самое. Не используйте 'next if line.empty?' В 'map', потому что это заставляет вас использовать' compact' после факта. Вместо этого отфильтруйте пустые строки, используя 'select' или' reject', прежде чем использовать 'map'. –

+0

Спасибо, я надеялся, что рядом не будет * собирая * ниль. Но я добавил, что это компактно, чтобы вытащить его. Вне темы: не должно быть способа ** пропустить ** значения? –

+0

Да. Используйте 'reject'. См. Http://stackoverflow.com/a/13485482/128421 –

3

Если вы хотите, чтобы первое слово из каждой строки из файла:

first_words = File.read(file_name).lines.map { |l| l.split(/\s+/).first } 

Это довольно просто. Давайте разберем его:

File.read(file_name) 

Считывает все содержимое файла и возвращает его в виде строки.

.lines 

Разбивает строку на символы новой строки (\n) и возвращает массив строк. Каждая строка представляет собой «строку».

.map { |l| ... } 

Array#map называет предоставленный блок, проходящий в каждом элементе и принимая возвращаемое значение блока, чтобы построить новый массив. Как только Array#map заканчивает, он возвращает массив, содержащий новые значения. Это позволяет вам преобразовать значения. В блоке выборки здесь |l| является частью блока params, означающей, что мы принимаем один аргумент, и мы будем ссылаться на него как l.

|l| l.split(/\s+/).first 

Это внутренний блок, я пошел вперед и включил здесь параметры блока для полноты. Здесь мы разделили строку на /\s+/. Это регулярное выражение, то \s означает любые пробелы (\t \n и пространство) и + после него означает один или более так \s+ означает один или более пробелам и, конечно, он будет пытаться соответствовать как многие последовательные символы пробелов, насколько это возможно. Передача этого значения в String#split вернет массив подстрок, которые происходят между указанным разделителем. Теперь наш разделитель был один или несколько пробелов, поэтому мы должны получить все между пробелами. Если бы у нас была строка "A list of words", мы получим ["A", "list", "of", "words"] после раздельного вызова. Это очень полезно. Наконец, мы вызываем .first, который возвращает первый элемент массива (в данном случае «первое слово»).

Теперь в Ruby вычисленное значение последнего выражения в блоке автоматически возвращается, и наше первое слово возвращается, и если этот блок передается на карту, мы должны получить массив из первых слов из файла. Чтобы продемонстрировать, давайте рассмотрим ввод (при условии, наш файл содержит):

This is line one 
And line two here 
Don't forget about line three 
Line four is very board 
Line five is the best 
It all ends with line six 

Запуск этого через линию выше, мы получим:

["This", "And", "Don't", "Line", "Line", "It"] 

Что первое слово из каждой строки.

+0

Это чрезвычайно полезно. Спасибо. .map все еще немного запутывает меня. Я изучаю то, что вы написали, и делайте больше исследований по этому вопросу. –

+1

Карта довольно проста: она просто запускает каждый элемент массива через подпрограмму и возвращает новый массив с этими значениями. Скажем, например, что вы хотели бы умножить каждое значение в массиве на два. Вы можете использовать карту: 'array_by_two = [1,2,3,4] .map {| val | val * 2} '. 'array_by_two == [2,4,6,8]' – Brennan

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