# Associative array naming indirection

**URL:** <https://www.ruby-forum.com/t/associative-array-naming-indirection/63849>\
**Category:** Ruby\
**Created:** [June 19, 2006, 9:51pm UTC](https://www.ruby-forum.com/t/associative-array-naming-indirection/63849 "2006-06-19T21:51:10Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [June 19, 2006, 9:51pm UTC](https://www.ruby-forum.com/t/associative-array-naming-indirection/63849/1 "2006-06-19T21:51:10Z")

</div>

I have an array of names in string form as an instance var. The class  
the array is in has a method that takes an array of string values.

I want to construct an associative array such that the names in the  
first array are the keys to the values in the received array.

## this throws an error:

def initialize  
@labels = [‘prov’, ‘area’, ‘zone’, district’, ‘postalcode’,  
‘city\_prov’, ‘addr’]  
@pageData = {}  
end

def adddata(data)  
max = data.length  
max -= 1  
0.upto(max) {|i| @pageData[@labels[i]] =\> data[i] }  
end

* * *

obviously, some giant conceptual leap needs to be made, or its a  
miniscule typo. (methinks the former)

Anyone got advice?

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [June 19, 2006, 10:13pm UTC](https://www.ruby-forum.com/t/associative-array-naming-indirection/63849/2 "2006-06-19T22:13:51Z")

</div>

On Jun 19, 2006, at 3:51 PM, dan donaldson wrote:

> ‘city\_prov’, ‘addr’]
> 
> obviously, some giant conceptual leap needs to be made, or its a  
> miniscule typo. (methinks the former)
> 
> Anyone got advice?

It’s hard to know without the error, but adddata() doesn’t look great  
to me. Try something like this:  
def add\_data(data)  
data.each\_index do |index|  
@pageData[@labels[i]] = data[i]  
end  
end

-Mat

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [June 19, 2006, 10:18pm UTC](https://www.ruby-forum.com/t/associative-array-naming-indirection/63849/3 "2006-06-19T22:18:19Z")

</div>

dan donaldson wrote:

> ‘city\_prov’, ‘addr’]
> 
> obviously, some giant conceptual leap needs to be made, or its a  
> miniscule typo. (methinks the former)
> 
> Anyone got advice?

What error? When?

-Justin

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [June 19, 2006, 10:21pm UTC](https://www.ruby-forum.com/t/associative-array-naming-indirection/63849/4 "2006-06-19T22:21:56Z")

</div>

uh … what’s the error

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [June 19, 2006, 10:36pm UTC](https://www.ruby-forum.com/t/associative-array-naming-indirection/63849/5 "2006-06-19T22:36:07Z")

</div>

dan donaldson wrote:

> ‘city\_prov’, ‘addr’]  
> @pageData = {}  
> end
> 
> def adddata(data)  
> max = data.length  
> max -= 1  
> 0.upto(max) {|i| @pageData[@labels[i]] =\> data[i] }  
> end

def add\_data(data)  
Hash[\*@labels.zip(data).flatten]  
end

Hash.[] takes an argument list with the even items being the keys and  
the odd items the values of the hash, i.e.

Hash[:a, 1, :b, 2, :c, 3] =\> {:a =\> 1, :b =\> 2, :c =\> 3}

The asterisk turns an array into an argument list, i.e.

foo(\*[:a, :b, :c])

is the same as

foo(:a, :b, :c)

You can read about Array#zip and Array#flatten on the documentation  
pages, or by using ri from the terminal, e.g.

$ ri Array#zip

Cheers,  
Daniel

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [June 19, 2006, 10:52pm UTC](https://www.ruby-forum.com/t/associative-array-naming-indirection/63849/6 "2006-06-19T22:52:16Z")

</div>

On Jun 19, 2006, at 20:51, dan donaldson wrote:

> ‘city\_prov’, ‘addr’]
> 
> obviously, some giant conceptual leap needs to be made, or its a  
> miniscule typo. (methinks the former)

It’s the typos, I’m afraid. First, you’ve got an unterminated string  
literal on ‘district’.

Second you’re using the wrong syntax for hash assignment, the =\>  
notation is used for hash literal values. It should look like this:  
@pageData[“something”] = “something else”

There’s also no reason to use #upto here - check the docs for Array  
and Enumerable, there are lots of methods which don’t require you to  
fiddle with finding sizes and the associated potential of fencepost  
errors. I’d do this, if it were me:

def add\_data(data)  
@page\_data[\*@labels.zip(data).flatten]  
end

Basically, zip combines the two arrays to something like this: [[‘a’,  
1], [‘b’, 2]], flatten changes this to [‘a’, 1, ‘b’, 2], and the \*  
transforms that from an array to a list (of arguments) to the Hash#[]  
method, which creates a new hash from that list of arguments.

matthew smillie.

docs for Array: [class Array - RDoc Documentation](http://ruby-doc.org/core/classes/Array.html)  
docs for Enumerable: [module Enumerable - RDoc Documentation](http://ruby-doc.org/core/classes/Enumerable.html)  
docs for Hash: [class Hash - RDoc Documentation](http://ruby-doc.org/core/classes/Hash.html)

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [June 19, 2006, 11:38pm UTC](https://www.ruby-forum.com/t/associative-array-naming-indirection/63849/7 "2006-06-19T23:38:41Z")

</div>

Matthew S. wrote:

> On Jun 19, 2006, at 20:51, dan donaldson wrote:
> 
> > ‘city\_prov’, ‘addr’]
> > 
> > obviously, some giant conceptual leap needs to be made, or its a  
> > miniscule typo. (methinks the former)
> 
> It’s the typos, I’m afraid. First, you’ve got an unterminated string  
> literal on ‘district’.

Ah yes.

The typo was in fact introduced during the editing of the copy/pasted  
text which contained a prefix that revealed the client’s name.

But it was in fact the ‘=\>’ operator. Thanks for pointing that out.  
Thanks also to everyone else, and esp. to Daniel, I’ll absorb what you  
wrote as well. A one line solution, that’s elegance. I imagine that if  
there’s a problem with the two arrays being of different lengths, I  
could truncate the longer one.

Related: The reason for futzing with .upto() was to deal with a variable  
length of input array needing to access labels in a given order. Is  
there a better way?

Working now. First post to the Ruby community: nice responses. I think I  
may like this.

---

<div class="post-metadata">

**Author:** ![dandiebolt](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/a87d85/32.png) [@dandiebolt](https://www.ruby-forum.com/u/dandiebolt)\
**Post date:** [June 20, 2006, 12:01am UTC](https://www.ruby-forum.com/t/associative-array-naming-indirection/63849/8 "2006-06-20T00:01:58Z")

</div>

> Related: The reason for futzing with .upto() was to deal with a  
> variable  
> length of input array needing to access labels in a given order. Is  
> there a better way?

That depends. If having ‘nil’ values in your hash is OK, you could  
still use #zip

labels = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’]  
data = [1, 2, 3]  
Hash[\*labels.zip(data).flatten]  
=\> {“a”=\>1, “b”=\>2, “c”=\>3, “d”=\>nil, “e”=\>nil, “f”=\>nil}

or #inject, if you’re feeling slightly obscurantist.

labels.inject({}) { |hsh, label| hsh.merge({label =\> data.shift}) }  
=\> {“a”=\>1, “b”=\>2, “c”=\>3, “d”=\>nil, “e”=\>nil, “f”=\>nil}

Or one of the other iteration methods in Array and Enumerable.

data.each\_index { |idx| hsh[labels[idx]] = data[idx] }  
data.each\_with\_index { |datum, idx| hsh[labels[idx] = datum }  
hsh  
=\> {“a”=\>1, “b”=\>2, “c”=\>3}

Browse through the docs, they’re the most help in situations like this.

matthew smillie.
