如何计算文本文件中的段落

时间:2018-09-25 03:55:10

标签: ruby

使用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")

3 个答案:

答案 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#countIO#read。 (由于File.superclass #=> IOread也在类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。最后一条语句的返回值将用作方法的返回值。