How to iterate over part of a hash in Ruby? - ruby

h = Hash.new
(1..100).each { |v| h.store(v * 2, v*v) }
What is the best way to iterate over a given part of the hash without using the keys? For example, from element 10 to element 20? Using Ruby 1.9.3.
EDIT - In response to Dave's comment:
Originally I wanted to access the data through keys (hence the hash). But I also want to iterate by element number. BTW, each element is a hash.
So, what is the best way to design a hash of hashes or array of hashes that can be iterated by element number or accessed by key? The data looks like the following. There are missing dates.
6/23/2011 -> 5, 6, 8, 3, 6
6/26/2011 -> 6, 8, 4, 8, 5
6/27/2011 -> 8, 4, 3, 2, 7

If I understand what you're asking for, you can iterate over a portion of your hash as follows. This gives you the 1001st through 2000th values:
h.keys[1000..1999].each do |key|
# Do something with h[key]
end

I think you better use Array for that (Hash in Ruby 1.9.3 are ordered but the access method is the keys). So:
a = h.values
# or
a = h.to_a

Convert it to an array, then slice it:
h.to_a[10..20].each { |k, v| do_stuff }
Note that before Ruby 1.9, the order of elements in a hash are not guaranteed, so this will not necessarily work as you expect.
Alternatively, you could use each_with_index and skip over the unwanted elements:
h.each_with_index do |(k, v), i|
next unless (10..20).include?(i)
# do stuff
end

h = Hash.new
(1..100).each { |v| h.store(v * 2, v*v) }
#for an array of arrays
h.drop(9).take(10) #plus an optional block
#if the slice must be a hash:
slice = Hash[h.drop(9).take(10)]
But if this is an often repeating operation you might be better off using a database.

Related

sorting unique values in an array with Ruby

Is there a way to write a method in Ruby which takes an array of items and returns the array without any duplicates. Without using Ruby’s uniq method?
So, the output of this array [1,5,"frog", 2,1,3,"frog"] will be [1,5,"frog",2,3]
You are getting an unexpected end-of-input because you are using parenthesis instead of braces to denote the block. Try:
my_array.to_a.select{ |i| i != i }
But even this isn't quite what you'd expect. Here is an alternative:
my_array.group_by{|item| item}.keys
Hope that helps
my_array = [1, 5, "frog", 2, 1, 3, "frog"]
uniques = []
my_array.each do |x|
uniques << x unless uniques.include?(x)
end
This iterates through my_array and only pushes to uniques elements it doesn't include.

How can I turn an array of keys into an array of values?

I have a hash like
hash = { 'burger': 2, 'kebab': 5, 'pizza': 10 }
and I have an array of its keys like
['burger', 'burger', 'pizza']
How would I create an array of the corresponding values? Would inject method be the best method to sum value array together?
Actually, you don't even need to prepare the key arrays.
To get the keys: hash.keys
To get the values: hash.values
If you want only certain values or values in certain order, then
a = [:burger, :pizza]
hash.values_at(*a) # => [2, 10]
You can use map as you've particularly said of wanting value of particular key in an array in a particular order. Else, you can use hash.values
arr = ['burger', 'burger', 'pizza']
results = arr.map { |key| hash[key] }

Ruby how to return an element of a dictionary?

# dictionary = {"cat"=>"Sam"}
This a return a key
#dictionary.key(x)
This returns a value
#dictionary[x]
How do I return the entire element
"cat"=>"Sam"
#dictionary
should do the trick for you
whatever is the last evaluated expression in ruby is the return value of a method.
If you want to return the hash as a whole. the last line of the method should look like the line I have written above
Your example is a bit (?) misleading in a sense it only has one pair (while not necessarily), and you want to get one pair. What you call a "dictionary" is actually a hashmap (called a hash among Rubyists).
A hashrocket (=>) is a part of hash definition syntax. It can't be used outside it. That is, you can't get just one pair without constructing a new hash. So, a new such pair would look as: { key => value }.
So in order to do that, you'll need a key and a value in context of your code somewhere. And you've specified ways to get both if you have one. If you only have a value, then:
{ #dictionary.key(x) => x }
...and if just a key, then:
{ x => #dictionary[x] }
...but there is no practical need for this. If you want to process each pair in a hash, use an iterator to feed each pair into some code as an argument list:
#dictionary.each do |key, value|
# do stuff with key and value
end
This way a block of code will get each pair in a hash once.
If you want to get not a hash, but pairs of elements it's constructed of, you can convert your hash to an array:
#dictionary.to_a
# => [["cat", "Sam"]]
# Note the double braces! And see below.
# Let's say we have this:
#dictionary2 = { 1 => 2, 3 => 4}
#dictionary2[1]
# => 2
#dictionary2.to_a
# => [[1, 2], [3, 4]]
# Now double braces make sense, huh?
It returns an array of pairs (which are arrays as well) of all elements (keys and values) that your hashmap contains.
If you wish to return one element of a hash h, you will need to specify the key to identify the element. As the value for key k is h[k], the key-value pair, expressed as an array, is [k, h[k]]. If you wish to make that a hash with a single element, use Hash[[[k, h[k]]]].
For example, if
h = { "cat"=>"Sam", "dog"=>"Diva" }
and you only wanted to the element with key "cat", that would be
["cat", h["cat"]] #=> ["cat", "Sam"]
or
Hash[[["cat", h["cat"]]]] #=> {"cat"=>"Sam"}
With Ruby 2.1 you could alternatively get the hash like this:
[["cat", h["cat"]]].to_h #=> {"cat"=>"Sam"}
Let's look at a little more interesting case. Suppose you have an array arr containing some or all of the keys of a hash h. Then you can get all the key-value pairs for those keys by using the methods Enumerable#zip and Hash#values_at:
arr.zip(arr.values_at(*arr))
Suppose, for example,
h = { "cat"=>"Sam", "dog"=>"Diva", "pig"=>"Petunia", "owl"=>"Einstein" }
and
arr = ["dog", "owl"]
Then:
arr.zip(h.values_at(*arr))
#=> [["dog", "Diva"], ["owl", "Einstein"]]
In steps:
a = h.values_at(*arr)
#=> h.values_at(*["dog", "owl"])
#=> h.values_at("dog", "owl")
#=> ["Diva", "Einstein"]
arr.zip(a)
#=> [["dog", "Diva"], ["owl", "Einstein"]]
To instead express as a hash:
Hash[arr.zip(h.values_at(*arr))]
#=> {"dog"=>"Diva", "owl"=>"Einstein"}
You can get the key and value in one go - resulting in an array:
#h = {"cat"=>"Sam", "dog"=>"Phil"}
key, value = p h.assoc("cat") # => ["cat", "Sam"]
Use rassoc to search by value ( .rassoc("Sam") )

What's a clean way to sort a hash in Ruby without returning an array of key-value pair arrays?

When I sort a hash in Ruby it returns an array of key-value pair arrays.
I would like it to return a hash.
What's a clean way to do this? inject?
Hashes aren't really sortable objects. Since Ruby 1.9, they maintain keys in the order in which they were added, which is convenient, but in terms of the data structure, order is not relevant.
You can test this by comparing { a: 1, b: 2 } == { b: 2, a: 1 } #=> true. The same is not true for arrays, in which the order is an important feature.
You'll find many methods in Ruby actually convert hashes to enumerables, which are closer to arrays in that they have a defined order. When returning a value from something like sort, you get an array.
You can easily convert it back into a hash using Hash[...]:
Hash[hash.sort(...)]
You can use Hash#[]
h = {a: 1, b:0, c: 3}
arr = h.sort {|(_,v),(_, v2) | v <=> v2 }
h2 = Hash[arr] #=> {:b=>0, :a=>1, :c=>3}
Note that this is possible because hashes are enumerated based on insertion order in Ruby. This is not normally the case for hashes in other languages
As others have warned, it generally is not good practice to rely on the order of hash elements.
Assuming you want to sort on values, here's another way:
h = {a: 2, b: 1, c: 4, d: 0}
Hash[h.to_a.sort_by(&:last)]
# => {:d=>0, :b=>1, :a=>2, :c=>4}
If you want to have an associative array that is intrinsically sorted by its keys (instead of having to manually insert in the right order as in the other solutions proposed), you should have a look at the RBTree gem which implements a red-black tree.

Can i check if an array e.g. just holds integers in ruby?

Title, i think is self declaring. I am kind of a java-developer and wanna ensure that my array holds just integer values. I know everything in ruby is a object. I find it inconvenient to loop through the array and make checks at every element. Is there any shortcut to this in ruby?
Use Enumerable#all? with a block. Integer numbers are instances of class Integer in ruby.
[1, 2, 3].all? {|i| i.is_a?(Integer) } # => true
[1, 2, 3, '4'].all? {|i| i.is_a?(Integer) } # => false

Resources