Ruby : メソッド定義について
受付中
回答 3
投稿
- 評価
- クリップ 0
- VIEW 789
テキスト処理についてのコードです。
Rubyでテキスト処理をしているのですが、同じような繰り返しが2回あるので、なんとかメソッドにして綺麗にコードを書けないかなと思って、試してみましたがやはりメソッドを作ることを今までしてこなかったためどのようにすればいいのかわかりません。
また、メソッドにしなくてもうまく動くので、無理にメソッド化する必要はないと思いますが、せっかくなので、今後のためにもメソッド作成を学んでおきたいと思いました。
以下のコード内の、filename_so ~ 最初のif文のendまでと、filename_nso ~2つめのif文のendまでをうまくメソッドにすることはできないでしょうか?
コード内の、soとnsoをメソッドの引数に取り、呼び出しの際にsoかnsoかを示せば動くと思いましたが、うまく実行されませんでした。
例えば、以下のように、abcメソッドに対してpointを引数にとり、呼び出しの際に、abc("so")、abc("nso")と試してみました。
そもそもメソッド定義や引数に対する考え方や使い方が間違っているのでしょうか?
def abc(point)
filename_"#{point}"
end
require 'lemmatizer' # 動詞を現形にするライブラリ
require 'active_support/all'
lem = Lemmatizer.new
Dir.chdir("../TOPIC") # TOPICフォルダへ移動
topic_name = Dir.glob("*") #TOPICフォルダ内のフォルダを保存
Dir.chdir("#{topic_name[0]}") # topic_nameの1番目のフォルダへ移動
Dir.chdir("SO/SO_SCRIPT") #SOフォルダのSO_SCRIPTフォルダへ移動
filename_so = Dir.glob("*") #SO_SCRIPTフォルダのファイルをfilename_soに保存
if filename_so.count == 0 # filename_soの数が0個なら
puts "Empty..."
else #0個でないなら
puts filename_so[0]
text_so = File.read(filename_so[0]) #filename_soの1番目のテキストをtext_soに保存
text_so.downcase!.gsub!(/\,|\./, '') #テキストの大文字の部分を小文字に置換し, ,と.を削除
text_so.gsub!(/\([a-z\s]+\)|\[[a-z\s]+\]|\'[a-z]+|\-|\—|\n|[0-9]+\:[0-9]+|[^a-z\s0-9]/, ' ') # ()と[]内の文字を空白に, 以降も同じように置換
text_so.gsub!(/\s+/, ' ') # 2個以上の空白を1つに置換
word = text_so.split # テキストを空白で区切りwordに保存
array = [] # 配列arrayを定義
word.each { |w| array << lem.lemma("#{w}").singularize } # word内の単語を現在形にし, かつ単数形にしてarrayに保存
array.sort! # arrayをソート
#puts array
end
Dir.chdir("../../NSO/NSO_SCRIPT")
filename_nso = Dir.glob("*")
if filename_nso.count == 0
puts "Empty..."
else
puts filename_nso[0]
text_nso = File.read(filename_nso[0])
text_nso.downcase!.gsub!(/\,|\./, '')
text_nso.gsub!(/\([a-z\s]+\)|\[[a-z\s]+\]|\'[a-z]+|\-|\—|\n|[0-9]+\:[0-9]+|[^a-z\s0-9]/, ' ')
text_nso.gsub!(/\s+/, ' ')
word = text_nso.split
array = []
word.each { |w| array << lem.lemma("#{w}").singularize }
array.sort!
#puts array
end
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
0
def abcの引数をDir.glob("*") の結果にして、中身の処理を
「filename_so ~ 最初のif文のendまで」にする
というのはどうでしょうか。
def abc(input)
filename_nso = input
以下略
end
使うときは
data = Dir.glob("*")
p abc(data)
みたいな感じです。
恐らく、array.sort!の結果が返ってくると思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
書き換えてみました
提示されたコードのみを頼りに、想像する部分は考えずに書いたため、おおきな勘違いなどあるかもわかりません
基本的に:
- 単純に処理が重複する部分
- 「何がしたいか」が(ちょっとだけ違うけど)同じ処理
は、メソッドとして切り出すことができると思います
require 'lemmatizer' # 動詞を現形にするライブラリ
require 'active_support/all'
def file_name_list(script_type:)
# TODO: このメソッドの呼び出し順序でカレントディレクトリが固定的に変化するか検証
case script_type
when :so_script
Dir.chdir('../TOPIC')
topic_names = Dir.glob('*')
Dir.chdir("#{topic_names.first}")
Dir.chdir('SO/SO_SCRIPT')
when :nso_script
Dir.chdir('../../NSO/NSO_SCRIPT')
end
Dir.glob('*')
end
def convert_text_to_words(file_name)
lem = Lemmatizer.new
text = File.read(file_name)
words =
text.downcase
.gsub(/\,|\./, '')
.gsub(/\([a-z\s]+\)|\[[a-z\s]+\]|\'[a-z]+|\-|\—|\n|[0-9]+\:[0-9]+|[^a-z\s0-9]/, ' ') # ()と[]内の文字を空白に置換
.gsub(/\s+/, ' ')
.split
words.map { |w| lem.lemma(w.to_s).singularize }.sort # word内の単語を現在形 かつ単数形に変換
end
# SO スクリプトの読み込み・変換処理
file_names_so = file_name_list(script_type: :so_script)
if file_names_so.count.zero?
puts 'Empty...'
else
puts file_names_so.first
array = convert_text_to_words(file_names_so.first)
# puts array
end
# NSO スクリプトの読み込み・変換処理
file_names_nso = file_name_list(script_type: :nso_script)
if file_names_nso.count.zero?
puts 'Empty...'
else
array = convert_text_to_words(file_names_nso.first)
puts file_names_nso.first
# puts array
end
コメントの書き方についてですが、1行1行の処理についてではなく、「それらをすることによって何が起きるのか」の説明が書かれていると、初めて読む際に分かり易しいのではないかとおもいました(もちろん、この質問のために詳細に書かれたのでしょう)
何か参考になれば幸いです
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
Dir.chdir("SO/SO_SCRIPT")以下、と
Dir.chdir("../../NSO/NSO_SCRIPT")以下、
酷似しているなら(diff取ってないですが、全く同じ処理ですよね?)、
ここから共通化できると思います
共通化することで、変数名をfilename_so, text_so, filename_so, text_nsoは
2つに減らせます。
共通化する、so, nsoどっちの処理かわからない、
というなら、puts Dir.pwd などすればいいと思います(下記の末尾の方に記載してます)
def abc(path)
Dir.chdir(path)
f_name = Dir.glob("*")
if f_name.count == 0
puts "Empty..."
else
puts f_name[0]
t = File.read(f_name[0])
t.downcase!.gsub!(/\,|\./, '')
t.gsub!(/\([a-z\s]+\)|\[[a-z\s]+\]|\'[a-z]+|\-|\—|\n|[0-9]+\:[0-9]+|[^a-z\s0-9]/, ' ')
t.gsub!(/\s+/, ' ')
word = t.split
array = []
word.each { |w| array << lem.lemma("#{w}").singularize }
array.sort!
#puts Dir.pwd
#puts array
end
end
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.10%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる