# How to make a variable based on array length and member value

**URL:** <https://www.ruby-forum.com/t/how-to-make-a-variable-based-on-array-length-and-member-value/171205>\
**Category:** Ruby\
**Created:** [June 28, 2009, 3:22pm UTC](https://www.ruby-forum.com/t/how-to-make-a-variable-based-on-array-length-and-member-value/171205 "2009-06-28T15:22:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![catsquotl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f9ae1b/32.png) [@catsquotl](https://www.ruby-forum.com/u/catsquotl)\
**Post date:** [June 28, 2009, 3:22pm UTC](https://www.ruby-forum.com/t/how-to-make-a-variable-based-on-array-length-and-member-value/171205/1 "2009-06-28T15:22:35Z")

</div>

Hi

I have an array full\_array[] of an arbitrary number of transaction  
objects.  
within the transaction is a Date member…

From the array I have created a new array years[].uniq! based on the  
Date.year members

what id like to do is take the new arrays members and use them as names  
for variables…

Say the array holds members for 2007, 2008, 2009  
i`d like to iterate through the full\_array and map all members from 2008  
in an array.

my options are creating an array based on years.length where each member  
holds all transactions from a specific year.

or iterate through the members of years and create an array based on the  
value or index of years…

I can`t seem to think of the logic to accomplish this…

Any ideas?

Eelco

---

<div class="post-metadata">

**Author:** ![catsquotl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f9ae1b/32.png) [@catsquotl](https://www.ruby-forum.com/u/catsquotl)\
**Post date:** [June 28, 2009, 4:23pm UTC](https://www.ruby-forum.com/t/how-to-make-a-variable-based-on-array-length-and-member-value/171205/2 "2009-06-28T16:23:31Z")

</div>

Catsquotl wrote:

> names for variables…
> 
> I can`t seem to think of the logic to accomplish this…
> 
> Any ideas?

Build up a suite of tests and the code in parallel, like this.

1. Think of a very simple case that isn’t yet covered by your code.  
Start with a very simple cases, and proceed to edge cases and  
pathological cases.

2. Write a new test to run your code and test the result, and run it. It  
will fail, because you HAVE NOT YET WRITTEN THE CODE. (If it doesn’t  
fail, you have made a mistake somewhere).

3. Alter your code to pass the new test and all of the old ones. Only  
when this is the case, may you proceed to stage 4.

4. Improve you code in some small way - Remove duplicate code, repair a  
bad choice of variable names etc.

5. After each improvement, Rerun all the tests. If any fail, you  
introduced an error. Fix before proceeding.

6. When the all pass and your code is nice and clean, save code (and  
tests) to the version control system.

7. If the code is not yet complete, go to step 1.

The key is to go in really tiny baby steps at stages 1 and 4, and to  
push stage 4 until you have really nice code you would be proud to show  
anyone. Note - you are testing for anything that might break/be broken,  
not aiming for 100% code coverage.

You will find that defining the tests will clarify your thinking about  
what is required. Stage 4 means the code remains clean and easy to  
modify. The test suite will stop you introducing errors into your code  
later.

When you are done, you have nice code, that you can demonstrate is  
correct.

Regards

Ian

---

<div class="post-metadata">

**Author:** ![catsquotl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f9ae1b/32.png) [@catsquotl](https://www.ruby-forum.com/u/catsquotl)\
**Post date:** [June 29, 2009, 2:06pm UTC](https://www.ruby-forum.com/t/how-to-make-a-variable-based-on-array-length-and-member-value/171205/3 "2009-06-29T14:06:19Z")

</div>

Catsquotl wrote:

> I have an array full\_array[] of an arbitrary number of transaction  
> objects.  
> within the transaction is a Date member…
> 
> From the array I have created a new array years[].uniq! based on the  
> Date.year members
> 
> what id like to do is take the new arrays members and use them as names  
> for variables…
> 
> Say the array holds members for 2007, 2008, 2009  
> i`d like to iterate through the full\_array and map all members from 2008  
> in an array.

Sounds like what you want is a Hash, not an Array. Something like:

year\_to\_members = {}  
members.each do |mem|  
y = mem.date.year  
year\_to\_members[y] ||= []  
year\_to\_members[y] \<\< mem  
end

p year\_to\_members[2009]

# this prints an array containing elememnts where date.year == 2009

As others will probably point out, this pattern can be simplified a bit.  
But hopefully it’s clear enough as a starting point.

The fundamental point is, you don’t want to create “names of variables”  
for each year - even though that is technically possible, as others may  
also point out. The right thing to do is to build a Hash, which is an  
object which associates a key (a year number) with a value (an array of  
transaction objects).

HTH,

Brian.

---

<div class="post-metadata">

**Author:** ![catsquotl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f9ae1b/32.png) [@catsquotl](https://www.ruby-forum.com/u/catsquotl)\
**Post date:** [June 29, 2009, 4:54pm UTC](https://www.ruby-forum.com/t/how-to-make-a-variable-based-on-array-length-and-member-value/171205/4 "2009-06-29T16:54:20Z")

</div>

2009/6/29 Brian C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Catsquotl wrote:

> > Say the array holds members for 2007, 2008, 2009  
> > i`d like to iterate through the full\_array and map all members from 2008  
> > in an array.
> 
> Sounds like what you want is a Hash, not an Array. Something like:

> As others will probably point out, this pattern can be simplified a bit.

Since you asked… 🙂

year\_to\_members = Hash.new {|h,k| h[k] = []}

members.each do |mem|  
year\_to\_members[mem.date.year] \<\< mem  
end

> The fundamental point is, you don’t want to create “names of variables”  
> for each year - even though that is technically possible, as others may  
> also point out. The right thing to do is to build a Hash, which is an  
> object which associates a key (a year number) with a value (an array of  
> transaction objects).

100% agree. It is definitively a bad idea to create variables with  
the year in their name.

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![catsquotl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f9ae1b/32.png) [@catsquotl](https://www.ruby-forum.com/u/catsquotl)\
**Post date:** [June 29, 2009, 7:11pm UTC](https://www.ruby-forum.com/t/how-to-make-a-variable-based-on-array-length-and-member-value/171205/5 "2009-06-29T19:11:00Z")

</div>

David A. Black schreef:

> 

Thanks for the reply…(Robert, Brian also)  
As a matter of fact I installed 1.9 last week awaiting the arrival of  
the well-grounded rubyist which should be sometime tomorrow

Eelco

---

<div class="post-metadata">

**Author:** ![catsquotl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f9ae1b/32.png) [@catsquotl](https://www.ruby-forum.com/u/catsquotl)\
**Post date:** [June 29, 2009, 5:38pm UTC](https://www.ruby-forum.com/t/how-to-make-a-variable-based-on-array-length-and-member-value/171205/6 "2009-06-29T17:38:19Z")

</div>

Hi –

On Sun, 28 Jun 2009, Catsquotl wrote:

> I can`t seem to think of the logic to accomplish this…  
> You could use group\_by (if you’ve got Ruby 1.9 or a 1.9-flavored 1.8):

full\_array.group\_by {|transaction| transaction.date.year }

That will give you a hash whose keys are the years and whose values  
are arrays of transaction objects, one such array per year-key.

David

---

<div class="post-metadata">

**Author:** ![catsquotl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f9ae1b/32.png) [@catsquotl](https://www.ruby-forum.com/u/catsquotl)\
**Post date:** [June 29, 2009, 7:20pm UTC](https://www.ruby-forum.com/t/how-to-make-a-variable-based-on-array-length-and-member-value/171205/7 "2009-06-29T19:20:59Z")

</div>

Ian H. schreef:

> 1. Alter your code to pass the new test and all of the old ones. Only
> 
> later.
> 
> When you are done, you have nice code, that you can demonstrate is correct.
> 
> Regards
> 
> Ian  
> Hi Ian,

As I am a relative beginner do you know any sites/articles/tutorials on  
test driven development?  
All I could find was sites on the benefits of tdd but not a tutorial  
within the ruby language… found a few in Java

I have manually tested all classes I write until now which is a bit  
tedious and time consuming…

I had a quick look at the test/unit Rdocs but am not quite certain on  
how to use them

Eelco
