Home » ATDD » Arrays and Hashes – II

Arrays and Hashes – II

We saw how methods relevant to particular data structure can be obtained from ruby – <object>.methods or <data_structure>.methods. 

>> ohio_cities = ["columbus", "cincinnati", "cleveland"]
=> ["columbus", "cincinnati", "cleveland"]
>> ohio_cities.methods
=> [:inspect, :to_s, :to_a, :to_ary, :frozen?, :==, :eql?, :hash, :[], :[]=, :at, :fetch, :first, :last, :concat, :<<, :push, :pop, :shift, :unshift, :insert, :each, :each_index, :reverse_each, :length, :size, :empty?, :find_index, :index, :rindex, :join, :reverse, :reverse!, :rotate, :rotate!, :sort, :sort!, :sort_by!, :collect, :collect!, :map, :map!, :select, :select!, :keep_if, :values_at, :delete, :delete_at, :delete_if, :reject, :reject!, :zip, :transpose, :replace, :clear, :fill, :include?, :<=>, :slice, :slice!, :assoc, :rassoc, :+, :*, :-, :&, :|, :uniq, :uniq!, :compact, :compact!, :flatten, :flatten!, :count, :shuffle!, :shuffle, :sample, :cycle, :permutation, :combination, :repeated_permutation, :repeated_combination, :product, :take, :take_while, :drop, :drop_while, :bsearch, :pack, :entries, :sort_by, :grep, :find, :detect, :find_all, :flat_map, :collect_concat, :inject, :reduce, :partition, :group_by, :all?, :any?, :one?, :none?, :min, :max, :minmax, :min_by, :max_by, :minmax_by, :member?, :each_with_index, :each_entry, :each_slice, :each_cons, :each_with_object, :chunk, :slice_before, :lazy, :nil?, :===, :=~, :!~, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
>> Array.methods
=> [:[], :try_convert, :allocate, :new, :superclass, :freeze, :===, :==, :<=>, :<, :<=, :>, :>=, :to_s, :inspect, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods, :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?, :const_missing, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set, :class_variable_defined?, :public_constant, :private_constant, :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?, :public_method_defined?, :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload, :autoload?, :instance_method, :public_instance_method, :nil?, :=~, :!~, :eql?, :hash, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]

Let’s see some of the methods to remove or change members in an array. Method named pop works in an opposite way to push method. It removes last member from an array. So, if I use ohio_cities.pop, “cleveland” will be removed from this array and it’ll have only two members remaining with it.

>> ohio_cities #output ohio_cities array
=> ["columbus", "cincinnati", "cleveland"]
>> ohio_cities.pop
=> "cleveland"
>> ohio_cities #ohio_cities array after pop method usage
=> ["columbus", "cincinnati"]

Similarly, shift method is a complimentary to unshift method we learned before. It removes first member from an array. Companion of insert method is delete_at method. It takes index value of a member that you want to get rid of in an array.

Some other methods that can come handy to you are –

>> fruits = ["apple", "orange", "papaya", "banana", "peach", "plum", "apricot", "pineapple"]
=> ["apple", "orange", "papaya", "banana", "peach", "plum", "apricot", "pineapple"]
>> fruits.delete("orange")
=> "orange"
>> fruits #fruits array after deleting orange
=> ["apple", "papaya", "banana", "peach", "plum", "apricot", "pineapple"]

>> fruits.reverse
=> ["pineapple", "apricot", "plum", "peach", "banana", "papaya", "apple"]

If you have looked carefully to methods applicable to an array, you’ll see two methods that may look similar – reverse and reverse! – while both of these methods reverse array members, one without exclamation mark doesn’t modify an original array & one with “!” modifies original array. So, after using fruits.reverse, if you look at fruits array, it’s still the same

>> fruits
=> ["apple", "papaya", "banana", "peach", "plum", "apricot", "pineapple"]

… and if you used reverse!, fruits array is reversed permanently.

>> fruits.reverse!
=> ["pineapple", "apricot", "plum", "peach", "banana", "papaya", "apple"]
>> fruits
=> ["pineapple", "apricot", "plum", "peach", "banana", "papaya", "apple"]

This is true for all the methods with “!”, they change associated object for good. Exclamation is ruby’s way of telling you to use these methods with caution.

>> fruits.sort
=> ["apple", "apricot", "banana", "papaya", "peach", "pineapple", "plum"]
>> fruits #original array remains unchanged
=> ["pineapple", "apricot", "plum", "peach", "banana", "papaya", "apple"]
>> fruits.sort!
=> ["apple", "apricot", "banana", "papaya", "peach", "pineapple", "plum"]
>> fruits #original array gets changed (sorted)
=> ["apple", "apricot", "banana", "papaya", "peach", "pineapple", "plum"]

>> fruits.empty?
fruits.empty?
=> false

Observe the question mark at the end of the method empty? Ruby has many methods that ends with ? These methods have return type of Boolean. It’s like asking a question to ruby, very intuitive! Here we are asking if fruits array is empty? and ruby replies back loud and clear – NO!

Similarly, let’s ask ruby if banana and mango are included in fruits array or not.

>> fruits.include?("banana")
=> true
>> fruits.include?("mango")
=> false

>> fruits.first #first member of an array
=> "apple"
>> fruits.last #last member of an array
=> "plum"
>> fruits.length #number of elements of an array
=> 7

>> fruits + ["mango"] #adds two arrays to generate third array
=> ["apple", "apricot", "banana", "papaya", "peach", "pineapple", "plum", "mango"]
>> fruits #fruits array remains unchanged
=> ["apple", "apricot", "banana", "papaya", "peach", "pineapple", "plum"]

>> fruits.concat(["mango"]) #adds second array to itself (modifies itself)
=> ["apple", "apricot", "banana", "papaya", "peach", "pineapple", "plum", "mango"]
>> fruits #fruits array has mango now
=> ["apple", "apricot", "banana", "papaya", "peach", "pineapple", "plum", "mango"]

>> [1, 2, 3] == [1, 2, 3] #two same arrays
=> true
>> [1, 2, 3] == [4, 5, 6] #two arrays with same length but different members
=> false
>> [1, 2, 3] == [1, 2, 3, 4] #two arrays with different length
=> false
>> [1, 2, 3] == ["a", "b", "c"] #two arrays with different members
=> false

>> odd = [1, 3, 5, 7, 9, 11]
=> [1, 3, 5, 7, 9, 11]
>> odd.slice(3) #member with index 3
=> 7
>> odd.slice(2, 3) #3 members starting at index 2
=> [5, 7, 9]
>> odd.slice(1..4) #members with index value between 1 and 4, including 1 and 4
=> [3, 5, 7, 9]
>> odd.slice(1...4) #members with index value between 1 and 4, including 1 but not 4
=> [3, 5, 7]

Similarly, another version of slice is slice!, which modifies the original array. There is no explicit reason to use slice method, you can access element by just referring its index value.

>> odd[1...4]
=> [3, 5, 7]
>> odd[1..4]
=> [3, 5, 7, 9]

Here interesting thing to learn is how negative index works with arrays in ruby. Just like first member of an array has index value of 0 and all subsequent members have progressing index values, last member of an array has index value of -1 and negative indices count backwards from the end of an array.

>> odd[-1]
=> 11
>> odd[-4]
=> 5
>> odd[-2..-2]
=> [9]
>> odd[-5..-2]
=> [3, 5, 7, 9]

There are a few array methods that aren’t widely used or not useful in routine programming, but provides powerful influence over a given array. The are some projects where they are actually broadly used. Some of these methods are –

zip, compact, collect, map, uniq, count, <=>, each, inspect

What? You didn’t find any example or explanation of what these methods are? Well, that’s your ‘end of the chapter exercise’! Good Luck!

Leave a comment