开发者

hash methods argument values

Working on trying to underst开发者_如何学Pythonand the syntax for calling on different values of a hash. For example lets say I am trying to delete 'pants' How do go about setting the argument for something like this:

products = {124 => ['shoes', 59.99], 352 => ['shirt', 19.99], 777 => ['pants', 19.87],
667 => ['jacket', 39.99], 898 => ['shoulder_holster', 22.78]}

While writing a menu driven program for this hash I'm including error checking before deleteing or adding a key this is what I have so far:

if a == 3                    # Loop delete a Product
 puts "Delete a Product"
 d = gets.to_s    # Get value for argument

   while products.has_value?(   d + syntax for right here????    )!= true do
   puts "This turned out false because product does not exsist!"
   d = gets.to_s
   end

 puts "Congrats your out of the loop"
 products.delete(d + again syntax problems ???? )
 puts products

end

How do I enter the syntax for the argument if I where to delete pants. Would it be ([d,:number]) I'm not having luck with any resources online with how to delete or add in this scenario. Any help or code example would be appreciated,

Matt


products.to_a.select {|a| a.last.first == 'pants' }

That will get you the record that matches 'pants'.

[[777, ["pants", 19.87]]]

So I think you'll want

while !products.to_a.select {|a| a.last.first == d }.empty?

on your loop then use Dafydd's line to delete the record.


It depends on whether the user is inputing the ID number or the name "pants". If the former:

if a == 3                    # Loop delete a Product
  puts "Delete a Product"
  d = gets    # Get value for argument

  until products.has_key?(d.to_i)
    puts "This turned out false because product does not exsist!"
    d = gets
  end

  puts "Congrats your out of the loop"
  products.delete(d.to_i)
  puts products
end

If it's "pants", then this is how you want to do it:

if a == 3                    # Loop delete a Product
  puts "Delete a Product"
  d = gets.strip    # Need to strip because otherwise the newline will wreck it

  until products.find {|key, val| val.first == d}
    puts "This turned out false because product does not exsist!"
    d = gets.strip
  end

  puts "Congrats your out of the loop"
  products.delete_if {|key, val| val.first == d}
  puts products
end


Writing a "delete named product from hash" method

There are shorter ways of doing it, but shooting for clarity I came up with this:

products = {124 => ['shoes', 59.99], 352 => ['shirt', 19.99], 777 => ['pants', 19.87],
667 => ['jacket', 39.99], 898 => ['shoulder_holster', 22.78]}

def wipeProduct(hash, nameToDelete) 
  hash.each do |i| 
    key = i[0]
    productName = i[1].first
    hash.delete(key) if productName==nameToDelete
  end
end

puts products.inspect
wipeProduct(products,'pants')
puts products.inspect
wipeProduct(products,'shoulder_holster')
puts products.inspect

bash-3.2$ ruby prod.rb 
{352=>["shirt", 19.99], 898=>["shoulder_holster", 22.78], 667=>["jacket", 39.99], 777=>["pants", 19.87], 124=>["shoes", 59.99]}
{352=>["shirt", 19.99], 898=>["shoulder_holster", 22.78], 667=>["jacket", 39.99], 124=>["shoes", 59.99]}
{352=>["shirt", 19.99], 667=>["jacket", 39.99], 124=>["shoes", 59.99]}

I don't know if it's possible for "pants" to occur in the hash in multiple places, but since I used "hash.each(...)", the method wipeProduct(hash, nameToDelete) will test every hash entry.

The input type bug and how to fix it

When you take input, you're assigning the string you captured to d. Here's the proof:

irb(main):010:0> d = gets.to_s
12
=> "12\n"
irb(main):011:0> d.class
=> String

You can convert that string to a Fixnum like this:

irb(main):012:0> d.to_i
=> 12
irb(main):013:0> d.to_i.class
=> Fixnum

All keys in the products hash are Fixnums. Here's the proof:

irb(main):014:0> products.keys.each {|i| puts i.class}
Fixnum
Fixnum
Fixnum
Fixnum
Fixnum
=> [352, 898, 667, 777, 124]

So you need to capture the value for the argument with this line:

d = gets.to_i    # Get value for argument

The deletion part of the answer:

From products, you can delete the pants entry programmatically with this:

products.delete(777)

Running it gets you this:

irb(main):003:0> products.delete(777)
=> ["pants", 19.87]

Notice that you supply the key value (in this case 777) to .delete() and that it returns an array consisting of the key and value in that order respectively.

An alternative implementation

I'm not sure if it's safe to modify a hash in a block that's iterating over the key-value pairs in the hash. If it isn't, you can just save up all the keys to be deleted and delete them after iterating over the hash:

def wipeProduct(hash, nameToDelete) 
  keysToDelete = []
  hash.each do |i| 
    key = i[0]
    productName = i[1].first
    keysToDelete << key if productName==nameToDelete
  end
  keysToDelete.each {|key| hash.delete(key) }
end


Here's the neater way to delete the "pants" entry:

def wipeProduct(hash, nameToDelete)
  hash.reject!{|key,value| nameToDelete==value.first}
end

The reject! block gets to see each key-value pair, and when it returns true, the key-value supplied will be removed from the hash.


if a == 3                    # Loop delete a Product
 puts "Delete a Product by its key number"
 d = gets
 while products.has_key?(d)!= false do
   puts "You have selected a key that is not currently in use"
   d = gets
 end
 puts "You have deleted"
 products.delete(d)
 puts products
end

This is what I ended up doing had some trouble with the until loop so swapped for a while loop though becasue it wouldn't accept newly entered keys for some reason

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜