[Eiffel] Array and Dictionary Tutorial
Author |
Message |
wtd
|
Posted: Tue Mar 02, 2004 10:57 pm Post subject: [Eiffel] Array and Dictionary Tutorial |
|
|
Arrays in Eiffel
Eiffel's arrays are quite powerful compared to those in either C++ or Java. Unlike arrays in either of those languages, arrays in Eiffel are first class objects, on par with all other objects, and requiring no special syntax.
In both C++ and Java, the size of an array is determinate. Arrays cannot grow beyond their initial size. In C++ that size is set when the program is compiled, while Java's arrays have their size set when the program is run, but ultimately here is the problem that they cannot grow.
Java's arrays have the redeeming quality of knowing their own length, unlike C++'s which require length to be monitored in a separate variable. Both provide classes to get around these limits, but those also have limitations, and mean having to know at least two different types of collections for doing the same thing.
But I digress, let's look at an Eiffel class TEST_PROGRAM with the standard make routine. In thise first example we'll declare and initialize an array of integers that starts out with 10 slots for integers, and the base index of zero.
code: | class TEST_PROGRAM
creation
make
feature { ANY }
make is
local
my_array : ARRAY[INTEGER]
base_capacity : INTEGER is 10
base_index : INTEGER is 0
do
create my_array.with_capacity(base_capacity, base_index)
end
end |
That simple. Now, if I want to set the value at index 3 to 42, and the value at index 5 to 2:
code: |
class TEST_PROGRAM
creation
make
feature { ANY }
make is
local
my_array : ARRAY[INTEGER]
base_capacity : INTEGER is 10
base_index : INTEGER is 0
do
create my_array.with_capacity(base_capacity, base_index)
my_array.put(42, 3)
my_array.put(2, 5)
end
end
|
Now I want to put at index 4, the result of multiplying index 3 and index 5 of my_array. This will show how the @ operator is overloaded in the array class.
code: |
class TEST_PROGRAM
creation
make
feature { ANY }
make is
local
my_array : ARRAY[INTEGER]
base_capacity : INTEGER is 10
base_index : INTEGER is 0
do
create my_array.with_capacity(base_capacity, base_index)
my_array.put(42, 3)
my_array.put(2, 5)
my_array.put((my_array @ 3) * (my_array @ 5), 4)
end
end
|
Now, we want to iterate through the array we've created and print each item to standard output.
code: |
class TEST_PROGRAM
creation
make
feature { ANY }
make is
local
my_array : ARRAY[INTEGER]
base_capacity : INTEGER is 10
base_index : INTEGER is 0
iter : ITERATOR[INTEGER]
do
create my_array.with_capacity(base_capacity, base_index)
my_array.put(42, 3)
my_array.put(2, 5)
my_array.put((my_array @ 3) * (my_array @ 5), 4)
from
iter := my_array.get_new_iterator
iter.start
until
iter.is_off
loop
std_output.put_integer(iter.item)
std_output.put_new_line
end
end
end
|
Pretty slick, eh? No having to keep track of the index and loop from 0 to 9 to output 10 items from my_array.
Dictionaries
Now, sometimes an array is actually a pretty kludgy way to keep track of data. After all, keys like 0, 3, and 57 aren't terribly descriptive. We need something like a dictionary. Oh, wait, we have one...
code: |
class TEST_PROGRAM
creation
make
feature { ANY }
make is
local
my_dict : DICTIONARY[STRING, STRING]
do
create my_dict.make
my_dict.put("My Name", "John Doe")
my_dict.put("My Dog", "Fluffy")
my_dict.put("My Car", "80s Civic)
std_output.put_string("My name is: " + (my_dict @ "My Name"))
std_output.put_new_line
end
end
|
No more having to remember what array index is associated with "My Name", just use that string to access... well... my name. Nifty, isn't it? |
|
|
|
|
|
Sponsor Sponsor
|
|
|
shorthair
|
Posted: Wed Mar 03, 2004 5:47 am Post subject: (No subject) |
|
|
sorry to complain about things, but is it not said in the sticky of this forum that this section is for pseudo programming not a certain language , its meant for things like the sin cos and tan thread , the game physics thread , you have kindof turned it into a little rugy and eiffel forum , |
|
|
|
|
|
jonos
|
Posted: Wed Mar 03, 2004 8:14 am Post subject: (No subject) |
|
|
something's messed up with the layout of this thread |
|
|
|
|
|
wtd
|
Posted: Wed Mar 03, 2004 4:13 pm Post subject: (No subject) |
|
|
Methinks the version of phpBB this forum is using needs to be patched as it has problems dealing with more than about two code tags in a post. This occurred in another thread I stared in this forum. |
|
|
|
|
|
Amailer
|
Posted: Wed Mar 03, 2004 6:15 pm Post subject: (No subject) |
|
|
oh man, dan better fix his bbcode... |
|
|
|
|
|
Dan
|
Posted: Thu Mar 04, 2004 6:12 pm Post subject: (No subject) |
|
|
i could but then we whould never see this fun stuff, lol.
ya if i ever have a day with out a test in some cores may be i will have time. |
Computer Science Canada
Help with programming in C, C++, Java, PHP, Ruby, Turing, VB and more! |
|
|
|
|
ljr1981
|
Posted: Wed Jan 15, 2014 3:30 pm Post subject: Re: [Eiffel] Array and Dictionary Tutorial |
|
|
From time to time, one will want to create multi-dimensional arrays in Eiffel. A typical answer to this need to to ask the programmer to create an ARRAY [ARRAY [ANY]], where each "level" of embedded ARRAY Generics is held to be a "dimension" of the array. Thus, ARRAY [ARRAY [ANY]] is claimed as a 2-dimensional array. While there is an ARRAY2 [G] class available for this, there is no ARRAY3 or ARRAY4.
What to do?
It is at this point we have a need for an n-dimensional array: ARRAYN [G -> ANY]. You can read a discussion of this class and get the code for it at the www.eiffelroom.org website.
The ARRAYN class is rather simple. Interally, it stores the n-dimensional array elements or items in a simple linear array:
code: |
feature {NONE} -- Implementation
internal_items: ARRAY [ANY]
-- Internal storage of items for Current.
|
This internal items array is not exported (e.g. not "public"). Instead, access to the array is handled by calls to:
code: |
l_array_item := my_array.item (<<3,6,7>>)
|
In the example above, the array access is performed through a call to the `item' feature of ARRAYN. What is passed is referred to as a "Manifest Array" (e.g. the items enclosed in double-angle-brackets like << and >>). Thus, the call item (<<3,6,7>>) tells us that the array is a 3-dimensional array and we are after the element located at 3,6,7 (x, y and z).
Putting or placing items into the array is just as straight forward:
code: |
my_array.put (l_item, <<6,4,1>>
|
The example above puts item `l_item' in a 3-dimensional array at element 6,4,1.
If you inspect the code for the ARRAYN class, you will find that getting items to and from the internal_items is controlled by "contracts" -- that is -- if the array is defined with 3 dimensional bounds and you attempt to send my_array.put (l_item, <<1,2,3,4>>) (e.g. 4 dimensions instead of 3), your call will cause a contract failure on the ensure of the `put' feature:
code: |
put (a_object: G; a_vector: ARRAY [INTEGER])
-- Put `object' at `index'
require
is_valid_vector: is_valid_vector (a_vector)
|
Where the `is_valid_vector' feature is:
code: |
is_valid_vector (a_vector: ARRAY [INTEGER]): BOOLEAN
-- Is `a_vector' valid, based on `bounds'?
do
Result := a_vector.count <= dimensions
Result := Result and across a_vector as ic_vector
all
ic_vector.item >= bounds [ic_vector.cursor_index].lower_nb and
ic_vector.item <= bounds [ic_vector.cursor_index].upper_nb
end
Result := Result and location (a_vector) <= max_size
end
|
The code above simply says: Make sure that the count of vectors in `a_vector' matches the dimensions of the array and that each boundary value in the manifest array is within the boundaries stored in the `bounds' array of TUPLEs. Inspection of the bounds feature will tell you that:
code: |
bounds: ARRAY [TUPLE [lower_nb, upper_nb: INTEGER]]
-- Lower and Upper bounds of Current.
|
|
|
|
|
|
|
|
|