Question

I am trying to create a simple bank account program to practice some Ruby. The idea is to create an array of hashes. However, I want to use user input to create a new hash, whether that be creating the title or simply numbering the entries something like user1 or user2.

If I use a set up that stores the username, pin, and balance all inside the hash, like so:

jhip = {
  :pin => 1234,
  :balance => 1000000
}

jdog = {
  :pin => 2345,
  :balance => 1000
}

accounts = [
  jhip,
  jdog
]

I feel it will be much easier to find the right username in the array and/or tell the user that their name has already been chosen than if I used a set up like this:

user1 = {
  :username => "jhip",
  :pin => 1234,
  :balance => 1000000
}

user2 = {
  :username => "jdog",
  :pin => 2345,
  :balance => 1000
}

accounts = [
  user1,
  user2
]

The real meat of this problem is getting the user input to be the title of the hash. I know the notation for creating a hash like this:

h = hash.new #or
hash = {}

But I don't know how to use the input as a title. When I store the input as a variable, I can play with the variable:

@username = gets.chomp
@username.to_i #or any method

But if I try to create a hash with the variable name, I overwrite the input.

@username = {} #no more using the response from gets

I guess what I'm looking for would be something like

@username = gets.chomp
@username.to_s => (some sort of code or command I'm unaware of) {}

And then I can push the key and value pairs into the hash. I don't know if I could use a block to accomplish this or something else. I'm still new to this, so I apologize if I bit off more than I can chew with this problem. Thanks for any help.

Was it helpful?

Solution

The following will create a hash with the username key assigned based on user input:

puts "Hey what's your username?"
username = gets.chomp
user = {
  username: username,
  pin: 10,
  balance: 100
}
puts "Your account is: #{user}"

Similarly, the following will insert a new hash into an array of hashes with the username key assigned based on user input:

def create_user(username)
  {
    username: username,
    pin: 10,
    balance: 100
  }
end

accounts = []
puts "Hey what's your username?"
username = gets.chomp
accounts.push(create_user(username))
puts "There are #{accounts.length} accounts"

In order to find an element in the array, you can simply iterate through each element and return if that element's username matches the correct username. For example

accounts = [create_user('alice'), create_user('bob')]

def find_by_username(accounts, username)
  accounts.each do |user|
    return user if user[:username] == username
  end
  nil
end

puts find_by_username(accounts, 'alice')
puts find_by_username(accounts, 'bob')
puts find_by_username(accounts, 'charles')

This method will iterate through each user and return the user if the username matches the given username. If no such user exists, it will return nil.

Ruby is nice in that a lot of those types of actions have been abstracted out -- arrays respond to a find method that returns the first element that matches a code block, or nil if no such element exists. So an alternate implementation of find_by_username would be

def find_by_username2(accounts, username)
  accounts.find do |user|
    user[:username] == username
  end
end

or more concisely

def find_by_username3(accounts, username)
  accounts.find { |user| user[:username] == username }
end

However looping through an array of hashes every time you want to find a user by username is a relatively slow operation. If you were to instead have a hash of hashes, the data structure might look like this:

accounts = {
  "alice" => { pin: 312, balance: -100 },
  "bob"   => { pin: 104, balance: 1000 }
}

and you would be able to find a user with the username of "bob" with accounts["bob"]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top