質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.35%

HashとArrayの使い方がわからず悩んでいます...

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,701

fujimaru

score 16

Ruby on Railsを先週から勉強はじめました。
以下のコードでわからないとこがあるので教えて下さい...。宜しくお願いします。

①『item.csv』というcvsデータを読み込む。
→csvデータの中には【商品コード】【商品名】【金額】が書いている。

※csvデータ

A1,たい焼き,500
A2,たこ焼き,300
A3,やきとり,100
B1,ビール,600
B2,焼きそば,300

②コマンドライン引数で、【商品コード】とマッチしていれば、以下のように表示する。

※実行結果【理想】

ruby Cart.rb A1 A2 A5 B2 →

【商品コード】A1【商品名】たい焼き【金額】500円
【商品コード】A2【商品名】たこ焼き【金額】300円
商品がありません。
【商品コード】B2【商品名】ビール【金額】600円

とコマンドライン引数の要素を一つづつ判別して、trueかfalseか調べたいのですが、実行すると、

※実行結果【現実】

ruby Cart.rb A1 A5[商品コード] A1 [商品名] たい焼き [金額] 500円
商品がありません。
商品がありません。
商品がありません。
商品がありません。
商品がありません。
商品がありません。
商品がありません。
商品がありません。
商品がありません。

と表示されてしまいます。readFileの中でループ処理を2回しているのが原因だと思うんですが、
その解決がわからないので、もしわかればおしえていただきたいです。
宜しくお願いします。

ITEM = "item.csv"

class Cart
    def initialize(code,name,value)
        @code = code
        @name = name
        @value = value
    end

    def toString
        return  "[商品コード] #{@code} [商品名] #{@name} [金額] #{@value}円"
    end
end


def readFile
    goods = File.read(ITEM)
    goods.each_line do |line|
        good = line.split(",")
        cart = Cart.new(good[0],good[1],good[2])
        for i in 0..ARGV.length
            hash = {good[0] => cart.toString()}
            if ARGV[i] == good[0]
                puts hash[ARGV[i]]
            else
                puts "商品がありません。"
            end
        end
    end
end


def exec
    readFile()
end


exec()

コードが読みにくいかもしれませんが、よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • iwamoto_takaaki

    2016/01/25 20:53

    実行してみて調べる回答者のために item.csv の中身と、入力したコマンドラインも載せてください。
    ちなみにコードやファイルの行頭と行末を「’’’」で囲むとコードが四角く囲まれ読みやすくなります。

    キャンセル

  • fujimaru

    2016/01/25 21:01

    ご指摘ありがとうございました。変更いたしました。引き続きお願いします。

    キャンセル

回答 3

checkベストアンサー

+3

「コマンドライン引数1つずつに対して、ファイルにあるかどうか調べる」
じゃなくて、
「ファイルの1行ずつについて、コマンドライン引数にあるかどうか調べる」
になっているので、表示される結果はファイルの行数と同じになります。コマンドラインにないファイルの行については、「商品がありません。」と出ます。

という説明で分かりますでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

以下のコードで解決できました。

やはりfor文を2回回していた箇所でエラーが出ていたので、
for文を分割して処理しました。

class Cart

    def initialize(code,name,capa)
        @code = code
        @name = name
        @capa = capa
    end

    def toString
        return  "[商品コード] #{@code} [商品名] #{@name} [金額] #{@value}円"
    end

end


class Goods

    Item = "item.csv"

    def readFile
        result = []
        goods = File.read(ITEM)
        goods.each_line do |line|
            good = line.split(",")
            ware = Cart.new(good[0],good[1],good[2])
            result << ware.toString
        end
        return result
    end


    def readCode
        code = []
        goods = File.read(ITEM)
        goods.each_line do |line|
            good = line.split(",")
            code << good[0]
        end
        return code
    end


    def getHash
        hash = {}
        for i in 0..readCode().length
            hash.store(readCode()[i], readFile()[i])
        end
        return hash
    end


    def argv
        for i in 0..ARGV.length-1
            if getHash()[ARGV[i]] != nil
                puts getHash()[ARGV[i]]
            else
                puts "商品がありません。"
            end
        end
    end


    def exec
        argv()
    end

    goods = Goods.new()
    goods.exec()

end

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

fujimaru さんの回答コードを少し書きなおしてみました。
ccc.rb

class Goods
  ITEM_FILE = 'item.csv'

  def read_csv
    csv = []
    File.read(ITEM_FILE).each_line do |line|
      csv << line.chop.split(',')
    end
    csv # 配列
  end

  def items_hash
    hash = {}
    csv = read_csv
    # 配列からハッシュを作る
    csv.each do |line|
      hash[line[0]] = { name: line[1], price: line[2].to_i }
    end
    hash
  end

  def exec(argv)
    hash = items_hash
    argv.each do |code|
      data = hash[code]
      if data
        puts "【商品コード】#{code} 【商品名】#{data[:name]} 【金額】#{data[:price]}"
      else
        puts "商品がありません。(#{code})"
      end
    end
  end
end

goods = Goods.new
goods.exec(ARGV)


実行結果

$ ruby ccc.rb A1 A2 A5 B2
【商品コード】A1 【商品名】たい焼き 【金額】500
【商品コード】A2 【商品名】たこ焼き 【金額】300
商品がありません。(A5)
【商品コード】B2 【商品名】焼きそば 【金額】300

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/01/31 22:27

    お!なるほど!僕は普段Javaを使っているのでJava的なコードになってしまうんですが、こんな書き方もあるんですね。とても参考になりました。ありがとうございます!

    キャンセル

  • 2016/01/31 22:39 編集

    hash = items_hash
    argv.each do |code|
    data = hash[code]
    if data
    puts "【商品コード】#{code} 【商品名】#{data[:name]} 【金額】#{data[:price]}"
    else
    puts "商品がありません。(#{code})"
    end


    ここの部分は
    data = nil => else
    という分岐になるんですか?

    キャンセル

  • 2016/01/31 22:52

    if data は if data != nil としてもよいです。

    キャンセル

  • 2016/01/31 22:53 編集

    もっと ruby らしく書くことは可能です。
    いろいろな書き方を考えてみるとよいと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る