0

私は現在Rubyを学んでおり、簡単なRubygrocery_listメソッドを書こうとしています。手順は次のとおりです。

食料品のリストを追跡するのに役立つプログラムを書きたいと思います。食料品 (「卵」など) を引数として取り、食料品リスト (つまり、各アイテムの数量を含むアイテム名) を返します。同じ引数を 2 回渡すと、数量がインクリメントされます。

def grocery_list(item)
  array = []
  quantity = 1
  array.each {|x| quantity += x }
  array << "#{quantity}" + " #{item}"
end

puts grocery_list("eggs", "eggs") 

卵を2回渡すことで「2個の卵」を返す方法をここで理解しようとしています

4

5 に答える 5

4

ハッシュとして使用できるさまざまなアイテムをカウントするのに役立ちます。ハッシュは配列に似ていますが、インデックスとして整数の代わりに文字列を使用します。

a = Array.new
a[0] = "this"
a[1] = "that"

h = Hash.new
h["sonja"] = "asecret"
h["brad"] = "beer"

この例では、ユーザーのパスワードを格納するためにハッシュが使用される可能性があります。しかし、あなたの例では、カウントするためのハッシュが必要です。shopping_list("eggs", "beer", "milk", "eggs") を呼び出すと、次のコマンドが実行されます。

h = Hash.new(0)   # empty hash {} created, 0 will be default value
h["eggs"] += 1    # h is now {"eggs"=>1}
h["beer"] += 1    # {"eggs"=>1, "beer"=>1}
h["milk"] += 1    # {"eggs"=>1, "beer"=>1, "milk"=>1}
h["eggs"] += 1    # {"eggs"=>2, "beer"=>1, "milk"=>1}

each-loop を使用して、ハッシュのすべてのキーと値を処理できます。

h.each{|key, value|  .... }

結果として必要な文字列を作成し、必要に応じてアイテムの数とアイテムの名前を追加します。ループ内では、最後に常にカンマと空白を追加します。これは最後の要素には必要ないため、ループが完了した後は

"2 eggs,  beer,  milk, "

最後のコンマと空白を取り除くには、chop! を使用できます。これは、文字列の末尾にある 1 文字を「切り取る」ものです。

output.chop!.chop!

食料品店リストの完全な実装を取得するには、もう 1 つ必要なことがあります。関数を次のように呼び出す必要があることを指定しました。

puts grocery_list("eggs",  "beer", "milk","eggs")

そのため、grocery_list 関数は、取得している引数の数を認識していません。これは、前に星印を付けて 1 つの引数を指定することで処理できます。この引数は、すべての引数を含む配列になります。

def grocery_list(*items)
   # items is an array
end    

だからここにあります:私はあなたのために宿題をして、grocery_listを実装しました。実装を理解するのに実際に苦労してください。単にコピーして貼り付けるだけではありません。

def grocery_list(*items)
  hash = Hash.new(0)
  items.each {|x| hash[x] += 1}

  output = ""
  hash.each do |item,number| 
     if number > 1 then 
       output += "#{number} " 
     end
     output += "#{item}, "
  end

  output.chop!.chop!
  return output
end

puts grocery_list("eggs",  "beer", "milk","eggs")
# output: 2 eggs,  beer,  milk 
于 2013-05-04T21:59:28.643 に答える
1

Enumerable#each_with_object次のような場合に役立ちます。

def list_to_hash(*items)
  items.each_with_object(Hash.new(0)) { |item, list| list[item] += 1 }
end

def hash_to_grocery_list_string(hash)
  hash.each_with_object([]) do |(item, number), result|
    result << (number > 1 ? "#{number} #{item}" : item)
  end.join(', ')
end

def grocery_list(*items)
  hash_to_grocery_list_string(list_to_hash(*items))
end

p grocery_list('eggs', 'eggs', 'bread', 'milk', 'eggs')

# => "3 eggs, bread, milk"

配列またはハッシュを反復して、便利な方法で別のオブジェクトを構築できるようにします。list_to_hashメソッドはそれを使用して、items 配列からハッシュを作成します (splat 演算子はメソッドの引数を配列に変換します) 。各値が 0 に初期化されるようにハッシュが作成されます。hash_to_grocery_list_stringメソッドはそれを使用して、コンマ区切りの文字列に結合される文字列の配列を作成します。

于 2013-05-04T23:48:19.300 に答える
1

これは、より冗長ですが、おそらくあなたの課題に対するより読みやすい解決策です。

def grocery_list(*items) # Notice the asterisk in front of items. It means "put all the arguments into an array called items"
  my_grocery_hash = {}  # Creates an empty hash

  items.each do |item| # Loops over the argument array and passes each argument into the loop as item.
     if my_grocery_hash[item].nil? # Returns true of the item is not a present key in the hash...
       my_grocery_hash[item] = 1 # Adds the key and sets the value to 1.
     else
       my_grocery_hash[item] = my_grocery_hash[item] + 1 # Increments the value by one.
     end
  end
  my_grocery_hash # Returns a hash object with the grocery name as the key and the number of occurences as the value.
end

これにより、値が 1 に設定されたキーとして各食料品が追加される空のハッシュ (他の言語では辞書またはマップと呼ばれる) が作成されます。同じ食料品店がメソッドのパラメーターとして複数回出現する場合、値がインクリメントされます。

テキスト文字列を作成し、ハッシュ オブジェクトの代わりにそれを返したい場合は、反復後に次のようにすることができます。

grocery_list_string = "" # Creates an empty string

my_grocery_hash.each do |key, value| # Loops over the hash object and passes two local variables into the loop with the current entry. Key being the name of the grocery and value being the amount.
  grocery_list_string << "#{value} units of #{key}\n" # Appends the grocery_list_string. Uses string interpolation, so #{value} becomes 3 and #{key} becomes eggs. The remaining \n is a newline character.
end

return grocery_list_string # Explicitly declares the return value. You can ommit return.

コメントに対する更新された回答:

ハッシュ反復を追加せずに最初のメソッドを使用すると、このように量を調べるために使用できるハッシュ オブジェクトが返されます。

my_hash_with_grocery_count = grocery_list("Lemonade", "Milk", "Eggs", "Lemonade", "Lemonade")

my_hash_with_grocery_count["Milk"]
--> 1

my_hash_with_grocery_count["Lemonade"]
--> 3
于 2013-05-04T21:44:38.413 に答える
1
def grocery_list(*item)
  item.group_by{|i| i}
end

p grocery_list("eggs", "eggs","meat")
#=> {"eggs"=>["eggs", "eggs"], "meat"=>["meat"]}

def grocery_list(*item)
  item.group_by{|i| i}.flat_map{|k,v| [k,v.length]}
end

p grocery_list("eggs", "eggs","meat")
#=>["eggs", 2, "meat", 1] 

def grocery_list(*item)
  Hash[*item.group_by{|i| i}.flat_map{|k,v| [k,v.length]}]
end

grocery_list("eggs", "eggs","meat")
#=> {"eggs"=>2, "meat"=>1}

grocery_list("eggs", "eggs","meat","apple","apple","apple") 
#=> {"eggs"=>2, "meat"=>1, "apple"=>3}

または@Leeが言ったように:

def grocery_list(*item)
  item.each_with_object(Hash.new(0)) {|a, h| h[a] += 1 }
end

grocery_list("eggs", "eggs","meat","apple","apple","apple") 
#=> {"eggs"=>2, "meat"=>1, "apple"=>3}
于 2013-05-04T21:03:17.637 に答える
1

配列の代わりにハッシュを使用する

簡単に数えたい場合は、ハッシュキーを使用して、数えたいものの名前を保持し、そのキーの値が数量になります。例えば:

#!/usr/bin/env ruby

class GroceryList
  attr_reader :list

  def initialize
    # Specify hash with default quantity of zero.
    @list = Hash.new(0)
  end

  # Increment the quantity of each item in the @list, using the name of the item
  # as a hash key.
  def add_to_list(*items)
    items.each { |item| @list[item] += 1 }
    @list
  end
end

if $0 == __FILE__
  groceries = GroceryList.new
  groceries.add_to_list('eggs', 'eggs') 
  puts 'Grocery list correctly contains 2 eggs.' if groceries.list['eggs'] == 2
end
于 2013-05-04T22:19:03.330 に答える