-2

I want to populate an array that has an integer and a hash, something like:

my_a=[Integer,{}]

then for example I am trying to have:

my_a[5,{:direction=>'up'}]
my_a[5,{:speed=>'fast'}]
my_a[3,{:direction=>'up'}]
my_a[3,{:speed=>'slow'}]

but I get

ArgumentError: wrong number of arguments(2 for 1)

How do I set my_a to have an entry for 5 with :direction => 'up'?

Maybe the whole thing should be a hash?

Trying to find someway to store this:

[0,{:top => ' ―― '},{:top_mid => '|__|'},{:bot_mid => '|  |'},{:bot => '――'}]
[1,{:top => ' ―― '},{:top_mid => '|__|'},{:bot_mid => '|  |'},{:bot => '――'}]
[2,{:top => ' ―― '},{:top_mid => '|__|'},{:bot_mid => '|  |'},{:bot => '――'}]
6
  • 1
    This argument error means that you are passing two arguments inside a block that only takes one argument.
    – Deej
    Commented Jun 15, 2013 at 14:31
  • 3
    When you state "an entry for 5", are you intending to fetch the hash {:direction=>'up'} if you ask for the value indexed by number 5? Because that is just a regular array my_a[5] = {:direction=>'up'} . . . what is different about your requirement? Commented Jun 15, 2013 at 14:31
  • 2
    my_a[...] is an array access. Array#[int, hash] is indeed not defined. That doesn't prevent you from using [int, hash] as an array literal: my_a = [5, {:direction => :up}] Commented Jun 15, 2013 at 14:34
  • 1
    What are you trying to do? Commented Jun 15, 2013 at 14:37
  • @junky Your question still is not clear. Your original text has direction and speed, while your edit has top and top_mid. When someone asks you "What are you trying to do?" you should not describe the data structures you think you need. You should describe your actual goal, the coding problem you are trying to solve. Step back two abstraction layers higher and tell us something like, "I'm writing an ASCII table and as I iterate through the rows I need to pick out the right pieces to show." Or whatever you are really doing.
    – Phrogz
    Commented Jun 15, 2013 at 15:33

4 Answers 4

4

I think you're looking for an array of hashes. Alternatively, if the numeric indices are not consecutive, a hash of hashes.

To create such an array, you can use an array literal ([...]) with hash literals ({...}) inside:

my_arr = [
  {:top => 'top0', :bot => 'bot0'},
  {:top => 'top1', :bot => 'bot1'}
]

(whitespace optional). Then my_arr[0] will refer to the first hash (with top0 and bot0 inside), and my_arr[1] will refer to the second hash. my_arr[0][:bot] will refer to the :bot value in the first hash, bot0.

Note that my_arr[2][:bot] will raise an exception since my_arr[2] is nil. Make sure to include any neccessary checks if you're accessing by an index.

See:

3

You wrote:

Trying to find someway to store this:

[0,{:top => ' ―― '},{:top_mid => '|__|'},{:bot_mid => '|  |'},{:bot => '――'}]
[1,{:top => ' ―― '},{:top_mid => '|__|'},{:bot_mid => '|  |'},{:bot => '――'}]
[2,{:top => ' ―― '},{:top_mid => '|__|'},{:bot_mid => '|  |'},{:bot => '――'}]

I don't think that's what you really want. What you show there is a discrete set of arrays, each of which has a single integer and a bunch of one-element hashes. I think you really want this:

a = [
  {:top => ' ―― ', :top_mid => '|__|', :bot_mid => '|  |', :bot => '――'},
  {:top => ' ―― ', :top_mid => '|__|', :bot_mid => '|  |', :bot => '――'},
  {:top => ' ―― ', :top_mid => '|__|', :bot_mid => '|  |', :bot => '――'}
]

With the above structure data, you can ask for items by index and name like so:

puts a[1][:top] #=> ' ―― '

You can create this either directly like I showed above, or you can add to it like so:

a = [] # Just an array; the contents are arbitrary

# Add an entire row at once…
a[0] = {:top => ' ―― ', :top_mid => '|__|', :bot_mid => '|  |', :bot => '――'}

# …or add to it piecemeal
a[1] = {} # An empty hash, waiting to be filled
a[1][:top] = ' ―― '
a[1][:bot] = ' ―― '
# et cetera

Note that if you do not know the index of each entry directly, but just want to add rows to the end, you can do:

a << {} # push this hash onto the end of the array
a.last[:top] = ' ―― '
# and so on
1
  • +1. I agree. The OP's original structure doesn't smell good and looks like it'd take some gnarly code to access/process it. Commented Jun 15, 2013 at 16:53
0

You are trying to store an hash with values of arrays of hashes. Try this:

my_a = {}
my_a[0] = [{:top => ' ―― '},{:top_mid => '|__|'},{:bot_mid => '|  |'},{:bot => '――'}]
my_a[1] = [{:top => ' ―― '},{:top_mid => '|__|'},{:bot_mid => '|  |'},{:bot => '――'}]
my_a[2] = [{:top => ' ―― '},{:top_mid => '|__|'},{:bot_mid => '|  |'},{:bot => '――'}]

Unless you want a hash of hashes...

my_a = {}
my_a[0] = {:top => ' ―― ', :top_mid => '|__|', :bot_mid => '|  |', :bot => '――'}
my_a[1] = {:top => ' ―― ', :top_mid => '|__|', :bot_mid => '|  |', :bot => '――'}
my_a[2] = {:top => ' ―― ', :top_mid => '|__|', :bot_mid => '|  |', :bot => '――'}

Also remember that Ruby is dynamically typed, and you can't declare the type stored in an array or hash.

5
  • This would be a hash of arrays of one-element hashes. I don't think OP wants that. Commented Jun 15, 2013 at 15:12
  • @JanDvorak: What does he want? (I have very little idea...)
    – Linuxios
    Commented Jun 15, 2013 at 15:14
  • I think he wants an array of hashes (an array of Objects is also fine) Commented Jun 15, 2013 at 15:16
  • @JanDvorak: I think he wants a foo of bars with consecutive bazzes in different universes. You seem to understand him better than I do. ;)
    – Linuxios
    Commented Jun 15, 2013 at 15:17
  • You seem to base your understanding on the code. I'm trying to base mine on the words and the data presented in the code (not its structure) Commented Jun 15, 2013 at 15:18
0

Seems like you want to store a specific structure in an array or in a hash. If you don't want to create a class for that, you can use OpenStruct:

require 'ostruct'
item = OpenStruct.new(top: ' ―― ', top_mid: '|__|', bot_mid: '|  |', bot: '――')
#=> #<OpenStruct top=" ―― ", top_mid="|__|", bot_mid="|  |", bot="――">, 1=>#<OpenStruct top=" ―― ", top_mid="|__|", bot_mid="|  |", bot="――">

You can get and set the attributes like this:

item.top                    # get "top" value
# => ' ―― '

item.top = "other value"    # set "top" value

Multiple items can be stored in an array:

array = []   # shortcut for Array.new

10.times { |index|
  array << OpenStruct.new(top: ' ―― ', top_mid: '|__|', bot_mid: '|  |', bot: '――')
}

array        #=> [<OpenStruct ...>, 2=>#<OpenStruct ...>, ...]
array[0]     #=> <OpenStruct ...>
array[0].top #=> ' ―― '

Or in a hash with numeric keys:

hash = {}    # shortcut for Hash.new

1.upto(10) { |index|
  hash[index] = OpenStruct.new(top: ' ―― ', top_mid: '|__|', bot_mid: '|  |', bot: '――')
}

hash         #=> {1=>#<OpenStruct ...>, 2=>#<OpenStruct ...>, ...}
hash[1]      #=> <OpenStruct ...>
hash[1].top  #=> ' ―― '

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.