使用oliver.txt
编写一个称为count_paragraphs
的方法来计算文本中的段落数。
在oliver.txt中,段落定界符由两个或多个连续的换行符组成,例如:\n\n
,\n\n\n
甚至是\n\n\n\n
。
您的方法应返回段落数或nil。
我有此代码,但它不起作用:
def count_paragraphs(some_file)
file_content = open(some_file).read()
count = 0
file_content_split = file_content.split('')
file_content_split.each_index do |index|
count += 1 if file_content_split[index] == "\n" && file_content_split[index + 1] == "\n"
end
return count
end
# test code
p count_paragraphs("oliver.txt")
答案 0 :(得分:1)
直接计数很容易:
file_content.split(/\n\n+/).count
或计数分隔符并添加一个:
file_content.scan(/\n\n+/).count + 1
答案 1 :(得分:0)
要确定段落数,无需构造数组并确定其大小。相反,可以通过创建枚举数并计算它将生成的元素数(在对文件内容进行一些清理之后)来直接对字符串进行操作。可以使用String#gsub方法的非常规形式(但非常有用)来完成。
代码
def count_paragraphs(fname)
(File.read(fname).gsub(/ +$/,'') << "\n\n").gsub(/\S\n{2,}/).count
end
示例
首先让我们构造一个文本文件。
str =<<BITTER_END
Now is the time
for all good
Rubiest to take
a break.
Oh, happy
day.
One for all,
all for one.
Amen!
BITTER_END
# " \n\nNow is the time\nfor all good\nRubiest to take\na break.\n \n \nOh, happy\nday.\n\nOne for all,\nall for one.\n\n \nAmen!\n"
注意嵌入的空格。
FNAME = 'temp'
File.write(FNAME, str)
#=> 128
现在使用此文件测试方法。
count_paragraphs(FNAME)
#=> 4
一个:
count_paragraphs('oliver.txt')
#=> 61
说明
第一步是通过删除换行符前的空格来处理格式错误的文本:
File.read(fname).gsub(/ +$/,'')
#=> "\n\nNow is the time\nfor all good\nRubiest to take\na break.\n\n\nOh, happy\nday.\n\nOne for all,\nall for one.\n\n\nAmen!\n"
接下来,添加两个换行符,以便我们可以将所有段落(包括最后一个段落)标识为包含非空格字符,后跟两个或多个换行符。 1 。
请注意,仅包含空格和换行符的文件被发现包含零段。
如果已知文件不包含格式错误的文本,则该方法的执行行可以简化为:
(File.read(fname) << "\n\n").gsub(/\S\n{2,}/).count
请参见Enumerable#count和IO#read。 (由于File.superclass #=> IO
,read
也在类File
的实例方法中,并且似乎在该类上的调用比在IO
上的调用更常见。)
请注意,没有块的String#gsub
返回一个枚举数(已应用Enumerable#count
),
此外:我相信,如果gsub
这种形式只有一个单独的名称,例如pattern_match
,它将被更广泛地使用。称其为gsub
似乎是用词不当,因为它与“替代”,“全局”或其他无关。
1我修改了原始答案以处理格式错误的文本,并以此为借口@Kimmo的想法,要求匹配包含非空白字符。
答案 2 :(得分:0)
一个循环来记住前一个字符以及在段落之内或之外的状态如何?
def count_paragraphs(some_file)
paragraphs = 0
in_paragraph = false
previous_char = ""
File.open(some_file).each_char do |char|
if !in_paragraph && char != "\n"
paragraphs += 1
in_paragraph = true
elsif in_paragraph && char == "\n" && previous_char == "\n"
in_paragraph = false
end
previous_char = char
end
paragraphs
rescue
nil
end
此解决方案不会构建全部内容的任何临时数组,因此您可以解析大型文件而无需将其读取到内存中。另外,没有正则表达式。
之所以添加rescue
是因为“您的函数应该返回段落数或nil”,而该数字并未明确定义何时应返回nil。在这种情况下,如果发生任何异常(例如,找不到文件或无法读取文件),它将被返回,这将引发rescue
捕获的异常。
在Ruby中,您不需要显式的return
。最后一条语句的返回值将用作方法的返回值。