Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert an array into an index hash in Ruby

I have an array, and I want to make a hash so I can quickly ask "is X in the array?".

In perl, there is an easy (and fast) way to do this:

my @array = qw( 1 2 3 ); my %hash; @hash{@array} = undef; 

This generates a hash that looks like:

{     1 => undef,     2 => undef,     3 => undef, } 

The best I've come up with in Ruby is:

array = [1, 2, 3] hash = Hash[array.map {|x| [x, nil]}] 

which gives:

{1=>nil, 2=>nil, 3=>nil} 

Is there a better Ruby way?

EDIT 1

No, Array.include? is not a good idea. Its slow. It does a query in O(n) instead of O(1). My example array had three elements for brevity; assume the actual one has a million elements. Let's do a little benchmarking:

#!/usr/bin/ruby -w require 'benchmark'  array = (1..1_000_000).to_a hash = Hash[array.map {|x| [x, nil]}]  Benchmark.bm(15) do |x|     x.report("Array.include?") { 1000.times { array.include?(500_000) } }     x.report("Hash.include?") { 1000.times { hash.include?(500_000) } } end 

Produces:

                     user     system      total        real Array.include?  46.190000   0.160000  46.350000 ( 46.593477) Hash.include?    0.000000   0.000000   0.000000 (  0.000523) 
like image 526
derobert Avatar asked Jan 04 '09 07:01

derobert


People also ask

How do you turn an array into a Hash in Ruby?

The to_h method is defined in the array class. It works to convert an array to a hash in the form of key-value pairs. The method converts each nested array into key-value pairs. The method also accepts a block.

How do you create a Hash in Ruby?

In Ruby you can create a Hash by assigning a key to a value with => , separate these key/value pairs with commas, and enclose the whole thing with curly braces.

What is TO_H in Ruby?

Ruby | Array to_h() function Array#to_h() : to_h() is a Array class method which returns the result of interpreting ary as an array of [key, value] pairs. Syntax: Array.to_h() Parameter: Array. Return: the result of interpreting ary as an array of [key, value] pairs.

Do hashes have indexes Ruby?

A Hash is a collection of key-value pairs. It is similar to an Array , except that indexing is done via arbitrary keys of any object type, not an integer index.


2 Answers

If all you need the hash for is membership, consider using a Set:

Set

Set implements a collection of unordered values with no duplicates. This is a hybrid of Array's intuitive inter-operation facilities and Hash's fast lookup.

Set is easy to use with Enumerable objects (implementing each). Most of the initializer methods and binary operators accept generic Enumerable objects besides sets and arrays. An Enumerable object can be converted to Set using the to_set method.

Set uses Hash as storage, so you must note the following points:

  • Equality of elements is determined according to Object#eql? and Object#hash.
  • Set assumes that the identity of each element does not change while it is stored. Modifying an element of a set will render the set to an unreliable state.
  • When a string is to be stored, a frozen copy of the string is stored instead unless the original string is already frozen.

Comparison

The comparison operators <, >, <= and >= are implemented as shorthand for the {proper_,}{subset?,superset?} methods. However, the <=> operator is intentionally left out because not every pair of sets is comparable. ({x,y} vs. {x,z} for example)

Example

require 'set' s1 = Set.new [1, 2]                   # -> #<Set: {1, 2}> s2 = [1, 2].to_set                    # -> #<Set: {1, 2}> s1 == s2                              # -> true s1.add("foo")                         # -> #<Set: {1, 2, "foo"}> s1.merge([2, 6])                      # -> #<Set: {1, 2, "foo", 6}> s1.subset? s2                         # -> false s2.subset? s1                         # -> true 

[...]

Public Class Methods

new(enum = nil)

Creates a new set containing the elements of the given enumerable object.

If a block is given, the elements of enum are preprocessed by the given block.

like image 193
rampion Avatar answered Sep 21 '22 15:09

rampion


try this one:

a=[1,2,3] Hash[a.zip] 
like image 27
edx Avatar answered Sep 23 '22 15:09

edx