Rudimentary irb testing suggests that Ruby Hash returns .keys and .values in matching order. Is it safe to assume that this is the case?
Yes. According to the Ruby Docs for Hash, "Hashes enumerate their values in the order that the corresponding keys were inserted." So you should always get the same order for a hash if it is created in the same way.
Depends on which Ruby version you are running.
Up to 1.8, enumeration was not insertion-ordered. Starting with 1.9, it will enumerate keys and values according to insertion order so, yes, it is safe to assume as long as you are running 1.9.
Related
What to do on a Ruby Hash, to optimize/fasten lookup ? (read only access)
Ex: freezing the hash, sorting the keys, forcing numerical keys...
Use frozen_string_literal:
frozen_string_literal reduces the generated garbage by ~100MB or ~20%! Free performance by adding a one line comment.
Conclusion
Gem authors: add # frozen_string_literal: true to the top of all Ruby files in a gem. It gives a free performance improvement to all your users as long as you don’t use String mutation.
Mike Perham: Ruby Optimization with One Magic Comment, 2018-02-28: https://www.mikeperham.com/2018/02/28/ruby-optimization-with-one-magic-comment/
Use Symbol as hash keys:
If you use Ruby 2.2, Symbol could be more performant than String as Hash keys.
Fast Ruby: https://github.com/fastruby/fast-ruby#hash
I am using ruby 1.8.7 on a production server and my hash get automatically get sorted while assigning it to variable. and in local machine its working fine.
This is output taken from my production console
>> a = {"b" => "a", "a" => "c"}
=> {"a"=>"c", "b"=>"a"}
>> a
=> {"a"=>"c", "b"=>"a"}
>>
Have any ideas? How do I avoid sorting of hash?
Thanks
You shouldn't / can't. If your script relies on some specific ordering, then you most likely want to use a list of key/value pairs instead. When using a hash in 1.8, the order is not defined in the specification. When using 1.9 it is defined to enumerate in the insertion order.
Hash in 1.8.7 isn't ordered, meaning you cannot rely on the order of the key-value pairs. That you're seeing them sorted alphanumerically is a coincidence.
If you need to know the order of the key/value pairs, you can use ActiveSupport::OrderedHash (or upgrade to Ruby 1.9+ and use the builtin Hash).
I am looking to make an efficient function to clear out a redis-based cache.
I have a method call that returns a number of keys from redis:
$redis.keys("foo:*")
That returns all the keys that start with "foo:". Next, I'd like to delete all the values for these keys.
One (memory-intensive) way to do this is:
$redis.keys("foo:*").each do |key|
$redis.del(key)
end
I'd like to avoid loading all the keys into memory, and then making numerous requests to the redis server.
Another way that I like is to use the splat operator:
keys = $redis.keys("foo:*")
$redis.del(*keys)
The problem is that I don't know what the maximum arity of the $redis.del method, nor of any ruby method, I can't seem to find it online.
What is the maximum arity?
#muistooshort in the comments had a good suggestion that turned out to be right, the redis driver knows what to do with an array argument:
# there are 1,000,000 keys of the form "foo:#{number}"
keys = $redis.keys("foo:*")
$redis.del(keys) # => 1000000
Simply pass an array of keys to $redis.del
Is it the same order in which the items were added to the Hash ?
The top of the Ruby 1.9.2 documentation for the Hash class declares:
Hashes enumerate their values in the order that the corresponding keys were inserted.
Cursory tests suggest that this does indeed apply to both Hash#keys and Hash#values, although the corresponding documentation for those methods doesn't seem to specify it.
In Ruby 1.8, there's no guaranteed order for the elements in a hash.
I am having trouble figuring out the elegant way to add an array of hashes
[{:a=>1,:b=>2,:c=>3},{:a=>1,:b=>2,:c=>3},{:a=>1,:b=>2,:c=>3}]
should return
[{:a=>3,:b=>6,:c=>9}]
I know it would probably involve mapping/reducing, but I can't figure out the right syntax, doesn't help that ruby-doc dot org doesn't match my version
I am using 1.8.7
array.inject{|x,y| x.merge(y){|_,a,b| a + b}}
(verified on Ruby 1.8.7)