This post was migrated from Justin’s personal blog, 'Codethinked.com.' Views, opinions, and colorful expressions should be taken in context, and do not necessarily represent those of Simple Thread (and were written under the influence of dangerous levels of caffeination).

Click here to view the entire IronRuby via C# series

Welcome back for part 5 in my learning Ruby via C# series. In this post I want to cover hashes (or associative arrays) and arrays in Ruby. These two data structures are used quite often in Ruby, and so we are going to spend a little bit of time going over them. But first I want to clear up some mistakes that I made in the first post of the series. In the first post I had explained what attribute accessors were and I showed a class that looked like this:

class Person  
    attr_accessor :count  
    @@count2 = 0  
  
    def count2  
        @@count2  
    end  
  
    def count2(value)  
        @@count2 = value  
    end  
end

Well, that isn’t exactly correct. Well, I was trying to show static variables in Ruby and I wanted to show the static version of “attr_accessor”. The first item I wanted to clear up is that I used instance method in this class because we had yet to cover static methods. This was done on purpose, but I wanted to show it as static now. The second thing is that you can do this in a shortened manner using the cattr_accessor method. The “c” stands for “class” since Ruby calls these “class variables and methods” and not “static”. The only problem is that this is part of ActiveSupport and not the standard Ruby libraries. ActiveSupport is a library of helper methods for Ruby on Rails, and currently has some issues running under IronRuby so I am not going to use it for now.

The second thing that I wanted to clear up, which actually was a mistake, is that the two “count2” methods are not what is defined. The second “count2” method should have an “=” between the word “count2” and the “(” that starts the argument list. So, if we don’t use the “cattr_accessor” method, our class (using static methods) will look like this:

class Person  
    attr_accessor :count  
    @@count2 = 0  
  
    def self.count2  
        @@count2  
    end  
  
    def self.count2=(value)  
        @@count2 = value  
    end  
end

And then we could access these new static methods like this:

Person.count2 = 123
puts Person.count2

Phew, now we can finally get to the new stuff! Let’s first talk about arrays. An array in Ruby is essentially the same as an array in C#. Lets say we wanted to declare an array of integers in C#:

int[] numberArray = { 1, 2, 3, 4, 5 };

Okay, now lets do the same thing in Ruby:

number_array = [1, 2, 3, 4, 5]

You can see that Ruby lets us define an array simply using square brackets and assigning the value to a variable. Now, while a C# array is immutable (meaning we can’t modify it) a Ruby array can be modified. So, in C# in order to add the number “6” to our array above we would have to do this:

int[] numberArray2 = new int[numberArray.Length + 1];
Array.Copy(numberArray, numberArray2, numberArray.Length);
numberArray2[numberArray2.Length - 1] = 6;

But in Ruby, we could simply do this:

number_array << 6

This uses the “<<” operator, therefore making Ruby arrays more similar to a C# collection than a C# array. In fact, Ruby arrays has methods for deletion and insertion. If we were to say:

number_array.delete(3)

Then when we output the array, we would get “[1,2,4,5]”. This is important because Ruby arrays are 0 based, just like C#. So, the “delete” method removes the item “3”, not the index (in fact, if there were more than one “3”, it would remove all of them). We would have to use the method “delete_at” in order to remove an item at an index:

number_array.delete_at(3)

We can also insert into the array using “insert” (the first parameter is the index, the second is the value):

number_array.insert(2,4)

So, what if we wanted to add an item to the end (without the “<<” operator):

number_array.push(7)

Okay, so we have a push method, what about pop? Of course, in Ruby you can use arrays just like stacks!

number_array.pop

Like I said before, in Ruby arrays are zero based, just like C#. They even use the same method to access the items. In C#:

int value = numberArray[0];

In Ruby:

value = number_array[0]

But what if we just wanted to see the last item in the array, but not remove it? In C# we would have to use the length of the array minus one:

int value = numberArray[numberArray.Length - 1];

But in Ruby, you can access arrays using negative indexes:

value = number_array[-1]

Negative arrays are indexed from the end of the array. How cool is that? Another cool thing you can do is use ranges to access an array:

number_array[0..2]

This would return “[1,2,3]”. As you can see, the Ruby array is very flexible.

So, enough about accessing arrays, what if we want to do some operations on these arrays. Lets add up all of the items in C#:

int total = 0;
foreach (int i in numberArray)
{
    total += i;
}
Console.WriteLine(total);

And what about in Ruby?

total = 0
number_array.each do |i|
    total += i
end
puts total

Lets do it more efficiently in C# using the LINQ aggregate method (if haven’t seen Aggregate (also called Fold) you can see an implementation and explanation here):

int total = numberArray.Aggregate((accumulator, i) => accumulator + i);
Console.WriteLine(total);

And then we will do it in Ruby using inject:

total = number_array.inject(0) { |accumulator, i| accumulator + i }
puts total

Sweet. You can really see how far C# has come to closing the gap in C# 3.0 with Linq. Before C# 3.0 and Linq we would be losing quite a bit of expressiveness here. Again, we can use the “select” method in C# and the “map” method in Ruby to transform items in an array. If we wanted to multiply each item in our array by 2, we could do this in C#:

var result = numberArray.Select(i => i * 2);

In Ruby we could do it like this:

number_array.map { |i| i * 2 }

Phew, I think we have had about enough with Arrays in Ruby. There is so many things that Ruby arrays can do, and we just don’t have the space to cover all of it. Go check out the Ruby docs if you want to see all of it.

Well, I was going to discuss hashes, but I think that arrays went on for a lot longer than I had originally planned. This seems to be a recurring theme, but there is just so much to talk about! I hope that you enjoyed the post and in the next one we are going to start talking about hashes.

Leave a Reply

Your email address will not be published. Required fields are marked *