Just do IT

思うは招く

Ruby基礎問題100本ノック#22 テキストの行数・単語数・文字数を数える

お題

テキストファイルからデータを読み込んで、次の数を数える処理を行うスクリプトを作成せよ。

  • 行数
  • 単語数
  • 文字数

サンプルテキストファイル foo.txt

山田孝之
鬼束ちひろ
マッスル北村
arnold schwarzenegger

回答

# ファイルの文字列を読み込む
str = File.read("foo.txt")

# 行数
def count_lines(str)
  str.lines.count
end

# 単語数
def count_words(str)
  ary = str.split(/\s+/)
  ary.size
end

# 文字数
def count_characters(str)
  ary = str.split(/\s+/)
  ary
    .join
    .chars
    .size
end

p count_lines(str) => 4
p count_words(str) => 5
p count_characters(str) => 35

説明

まずはFileクラスのreadメソッドを使い、テキストファイルの文字列を読み込む。

# ファイルの文字列を読み込む
str = File.read("foo.txt")
=> "山田孝之\n鬼束ちひろ\nマッスル北村\narnold schwarzenegger"

String#lines.countで行数を取得できる。

def count_lines(str)
  str.lines.count
end

ここで単語数とは、「空白や改行文字以外の文字の並び」と定義されているので、取得した文字列を空白や改行文字で区切って配列へ入れる。そしてsizeメソッドで要素数を取得。

# 単語数
def count_words(str)
  p ary = str.split(/\s+/)
  ary.size
end
=> ["山田孝之", "鬼束ちひろ", "マッスル北村", "arnold", "schwarzenegger"]

文字数を数える場合、まずは単語数をカウントしたときのように空白や改行文字を省いて配列へ入れる。 そして、それらを一旦文字列になおして、charsメソッドで一文字ずつ配列にいれてsizeを取得する。

# 文字数
def count_characters(str)
  ary = str.split(/\s+/)
  ary
    .join
    .chars
    .size
end

ary.join.charsをしたときの配列

# ary.join
=> "山田孝之鬼束ちひろマッスル北村arnoldschwarzenegger"

#ary.join.chars
=> ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "a", "r", "n", "o", "l", "d", "s", "c", "h", "w", "a", "r", "z", "e", "n", "e", "g", "g", "e", "r"]

学び

これが冗長すぎる。

# 文字数
def count_characters(str)
  ary = str.split(/\s+/)
  ary
    .join
    .chars
    .size
end

配列→文字列→配列にしているのが冗長。

File.open(file) do |io|
    io.each { ~~ }
end

の中で処理してもよかった。