【问题标题】:I don't understand why is this step necessary to count the number of chars in text document我不明白为什么需要此步骤来计算文本文档中的字符数
【发布时间】:2017-03-29 11:48:41
【问题描述】:
lines = File.readlines("new text document.txt")
lines_count = lines.size
text = lines.join
no_of_chars = text.length

puts "number of lines: #{lines_count}"
puts "number of chars: #{no_of_chars}"

您好,我的目标是计算文本文档中的字符数。我不明白的是为什么需要lines.join?当你lines.join 时,程序在做什么?因为当我puts linesputs lines.join 时,程序会打印出完全相同的内容。因此我所做的(以及我认为正确的)是

no_of_chars = lines.length

这显然是错误的,因为这样做no_of_char 将导致输出与行数相同。

【问题讨论】:

  • 在 Ruby 2.4 中,您可以调用 lines.sum(&:length) 来获取总长度。

标签: arrays ruby string


【解决方案1】:

当你这样做时

lines = File.readlines("new text document.txt")

你有一个字符串数组,即:

lines #=> [
  "The surgeon lead over ...\n", # <- There's a newline at the end of each string
  "The medical gentleman ...\n",
]

数组中的条目与文本文件中的行数一样多。这就是为什么你要计算行数:

lines_count =lines.size

当您调用lines.join 时,您实际上是将所有字符串一个接一个地连接在一起

text = lines.join
text # => "The surgeon ... dress the infant"

要计算字符串的字符数,您只需调用length就可以了。

它们在控制台上看起来与您相似的原因是,当您打印它们时,它们会以相同的方式呈现。为了突出差异,您可以在每个人上调用inspect

puts lines.inspect
puts text.inspect

【讨论】:

  • 嗨,如果我使用.join 将所有字符串连接在一起,这是否意味着所有行都没有间距地组合在一起。也就是说文本#=>“外科医生......晚安!'医疗绅士......婴儿。”?由于在方法.join 中没有说明任何参数(在这种情况下为空格)
  • 你是对的。如果你想在数组的每个条目之间有一个空格,你可以这样做lines.join(" ")
  • 但是我尝试将puts lines.join 运行到我的控制台,结果是行以间距分隔。尽管我没有说明方法 .join 的参数(空格)
  • readlines 不会去除换行符,因此这些字符仍然存在于您的各个行中。所以当你加入它们时,它们之间仍然会有换行符。
  • @davidstanley 有没有关于它的 ruby​​ 文档,以便我可以阅读更多内容?
【解决方案2】:

反过来可能会更简洁,即通过IO.read 将整个文件作为单个字符串读取,然后使用String#lines 拆分行:

text = IO.read('document.txt')
no_of_chars = text.length
lines_count = text.lines.length

puts "number of lines: #{lines_count}"
puts "number of chars: #{no_of_chars}"

请注意,String#length 将计算任何字符,包括标点符号、空格和换行符。

【讨论】:

    【解决方案3】:

    lines 是一个数组。数组的可视化类似于加入数组的结果:

    numbers = ['11', '22', '33', '44']
    puts numbers
     # 11
     # 22
     # 33
     # 44
    puts numbers.join
     # 11223344
    

    如果数组末尾有新行(就像您刚刚从文件中获取行的情况一样),您将无法区分两者。然而它们是不同的:

    numbers.length      # => 4
    numbers.join.length # => 8
    

    数组的长度会告诉你数组有多少元素。在您的情况下-文件中有多少行。就我而言 - 多少个数字。

    如果加入数组,则连接每一行。因此,结果字符串的长度将为您提供整个文件中有多少个字符。就我而言 - 多少位数。

    【讨论】:

      【解决方案4】:

      我不明白的是为什么需要lines.join

      在一个字符串中获取全文(数组中的所有项目)

      当你lines.join时程序在做什么?

      检查documentation

      因为当我puts linesputs lines.join 程序打印出来 完全一样的东西。

      因为lines 在运行puts lines 时是一个数组,所以它是shows an array as stringjoin() 将所有数组项合并为一个字符串。

      >> puts "fooo" 
      #> fooo 
      => nil 
      >> puts ["fooo"].join
      #> fooo
      => nil
      

      因此要获取文本中的字符数,为什么我无法 只需使用no_of_chars = lines.length?

      因为当您使用lines.length 时,它会显示数组的长度。

      【讨论】:

        【解决方案5】:

        读取文件不是查找字符数的好方法,因为它不可扩展。现在很容易找到 GB 范围内的文件,尤其是在生产环境中,当您尝试 slurp 整个文件时,会严重影响您的 Ruby 进程。

        改用这个:

        char_size = 0
        File.foreach('path/to/file.txt') do |li|
          char_size += li.size
        end
        

        foreach 逐行读取文件,对于超过 1MB 的文件,这与使用 readreadlines 一样快或更快,同时仍然具有可扩展性。

        有关详细信息,请参阅“Why is "slurping" a file not a good practice?”。

        如果您知道文件包含单字节字符,例如传统的 ASCII、ISO-8859 或 Win-1252 字符集,您可以使用 File.size('path/to/file.txt') 更快地完成。

        使用size 根本不需要读取文件,因此它比任何实际打开和读取内容的解决方案都要快。

        【讨论】:

          猜你喜欢
          • 2012-03-03
          • 2019-08-26
          • 1970-01-01
          • 2015-07-31
          • 1970-01-01
          • 2021-09-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多