Creating a Hash from Two Arrays
From Rosetta Code
Programming Task
This is a programming task. It lays out a problem which Rosetta Code users are encouraged to solve, using languages they know.
Contents |
[edit] Ada
Works with: GNAT version GPL 2007
with Ada.Strings.Hash; with Ada.Containers.Hashed_Maps; with Ada.Text_Io; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; procedure Hash_Map_Test is function Equivalent_Key (Left, Right : Unbounded_String) return Boolean is begin return Left = Right; end Equivalent_Key; function Hash_Func(Key : Unbounded_String) return Ada.Containers.Hash_Type is begin return Ada.Strings.Hash(To_String(Key)); end Hash_Func; package My_Hash is new Ada.Containers.Hashed_Maps(Key_Type => Unbounded_String, Element_Type => Unbounded_String, Hash => Hash_Func, Equivalent_Keys => Equivalent_Key); type String_Array is array(Positive range <>) of Unbounded_String; Hash : My_Hash.Map; Key_List : String_Array := (To_Unbounded_String("foo"), To_Unbounded_String("bar"), To_Unbounded_String("val")); Element_List : String_Array := (To_Unbounded_String("little"), To_Unbounded_String("miss"), To_Unbounded_String("muffet")); begin for I in Key_List'range loop Hash.Insert(Key => (Key_List(I)), New_Item => (Element_List(I))); end loop; for I in Key_List'range loop Ada.Text_Io.Put_Line(To_String(Key_List(I)) & " => " & To_String(Hash.Element(Key_List(I)))); end loop; end Hash_Map_Test;
[edit] C++
By strict definition a std::map is not a hash, but it provides the same functionality. The C++-200x update to the C++ standard is incorporating hashes. When they are standardized the code below can change std::map to std::unordered_map and this will technically be a hash table. The core idea, turning two sequences into an associative mapping, is valid either way.
#include <map>
#include <string>
int
main( int argc, char* argv[] )
{
std::string keys[] = { "1", "2", "3" } ;
std::string vals[] = { "a", "b", "c" } ;
std::map< std::string, std::string > hash ;
for( int i = 0 ; i < 3 ; i++ )
{
hash[ keys[i] ] = vals[i] ;
}
}
Alternatively:
#include <map> // for std::map
#include <algorithm> // for std::transform
#include <string> // for std::string
#include <utility> // for std::make_pair
int main()
{
std::string keys[] = { "one", "two", "three" };
std::string vals[] = { "foo", "bar", "baz" };
std::map<std::string, std::string> hash;
std::transform(keys, keys+3,
vals,
std::inserter(hash, hash.end()),
std::make_pair<std::string, std::string>);
}
[edit] C #
System.Collections.HashTable h = new System.Collections.HashTable();
string[] arg_keys = {"foo","bar","val"};
string[] arg_values = {"little", "miss", "muffet"};
//Some basic error checking
int arg_length = 0;
if ( arg_keys.Length == arg_values.Length ) {
arg_length = arg_keys.Length;
}
for( int i = 0; i < arg_length; i++ ){
h.add( arg_keys[i], arg_values[i] );
}
Alternate way of adding values
for( int i = 0; i < arg_length; i++ ){
h[ arg_keys[i] ] = arg_values[i];
}
[edit] D
string[] keys = ["one", "two", "three"] int[] values = [1, 2, 3]; int[string] hash; foreach(idx, key; keys) hash[key] = values[idx];
[edit] E
def keys := ["one", "two", "three"] def values := [1, 2, 3] __makeMap.fromColumns(keys, values)
[edit] Factor
USING: hashtables ;
{ "one" "two" "three" } { 1 2 3 } zip >hashtable
[edit] Groovy
keys = ['a','b','c']
vals = ['aaa', 'bbb', 'ccc']
hash = [:]
i = 0
keys.each { entry ->
hash.put(entry, vals[i++])
}
[edit] Haskell
Works with: GHCi version 6.6
import Data.Map makeMap ks vs = fromList $ zip ks vs mymap = makeMap ['a','b','c'] [1,2,3]
[edit] J
f=: y {~ x&i.
For example:
x=: 10?.100
y=: > ;:'zero one two three four five six seven eight nine'
f=: y {~ x&i.
x
46 99 23 62 42 44 12 5 68 63
$y
10 5
f 46
zero
f 99
one
f 63 5 12 5 23
nine
seven
six
seven
two
Here, x is a list of 10 integers between 0 and 99 chosen at random without repetition, and y is a 10 by 5 character matrix.
[edit] Java
import java.util.HashMap;
public static void main(String[] args){
String[] keys= {"a", "b", "c"};
int[] vals= {1, 2, 3};
HashMap<String, Integer> hash= new HashMap<String, Integer>();
for(int i= 0; i < keys.length; i++){
hash.put(keys[i], vals[i]);
}
}
[edit] JavaScript
var keys = ['a', 'b', 'c'];
var values = [1, 2, 3];
var map = {};
for(var i in keys) {
map[ keys[i] ] = values[i];
}
[edit] OCaml
The idiomatic solution uses lists rather than arrays.
let keys = [ "foo"; "bar"; "baz" ] and vals = [ 16384; 32768; 65536 ] and hash = Hashtbl.create 0;;
List.iter2 (Hashtbl.add hash) keys vals;;
In the extremely unlikely event that it was actually necessary to use arrays, the solution would become slightly less elegant: (except using the ExtLib which provides the equivalent Array.iter2)
let keys = [| "foo"; "bar"; "baz" |] and vals = [| 16384; 32768; 65536 |] and hash = Hashtbl.create 0;;
for i = 0 to Array.length keys - 1 do Hashtbl.add hash keys.(i) vals.(i) done;;
In either case, an exception is raised if the inputs are different lengths.
[edit] Perl
Works with: Perl version 5
Library: List::MoreUtils
use List::MoreUtils qw(zip); my @keys = qw(a b c); my @vals = (1, 2, 3); my %hash = zip @keys, @vals;
Using no modules:
my %hash;
@hash{qw(a b c)} = (1, 2, 3);
[edit] PHP
Works with: PHP version 5
$keys = array('a', 'b', 'c');
$values = array(1, 2, 3);
$hash = array_combine($keys, $values);
Works with: PHP version 4
$keys = array('a', 'b', 'c');
$values = array(1, 2, 3);
$hash = array();
for ($idx = 0; $idx < count($keys); $idx++) {
$hash[$keys[$idx]] = $values[$idx];
}
[edit] Pop11
vars keys = { 1 a b c};
vars vals = { 2 3 valb valc};
vars i;
;;; Create hash table
vars ht = newmapping([], 500, 0, true);
;;; Loop over input arrays (vectors)
for i from 1 to length(keys) do
vals(i) -> ht(keys(i));
endfor;
[edit] Prolog
% this one with side effect hash table creation :-dynamic hash/2. make_hash([],[]). make_hash([H|Q],[H1|Q1]):- assert(hash(H,H1)), make_hash(Q,Q1). :-make_hash([un,deux,trois],[[a,b,c],[d,e,f],[g,h,i]]) % this one without side effects make_hash_pure([],[],[]). make_hash_pure([H|Q],[H1|Q1],[hash(H,H1)|R]):- make_hash_pure(Q,Q1,R). :-make_hash_pure([un,deux,trois],[[a,b,c],[d,e,f],[g,h,i]],L),findall(M,(member(M,L),assert(M)),L).
[edit] Python
Works with: Python version 2.3+
keys = ['a', 'b', 'c'] values = [1, 2, 3] hash = dict(zip(keys, values)) # Lazily: from itertools import izip hash = dict(izip(keys, values))
Works with: Python (any version)
keys = ['a', 'b', 'c'] values = [1, 2, 3] hash = {} for i range(len(keys)): hash[keys[i]] = values[i]
The original (Ruby) example uses a range of different types as keys. Here is similar in python (run at the shell):
>>> class Hashable(object): def __hash__(self): return id(self) ^ 0xBEEF >>> my_inst = Hashable() >>> my_int = 1 >>> my_complex = 0 + 1j >>> my_float = 1.2 >>> my_string = "Spam" >>> my_bool = True >>> my_unicode = u'Ham' >>> my_list = ['a', 7] >>> my_tuple = ( 0.0, 1.4 ) >>> my_set = set(my_list) >>> def my_func(): pass >>> class my_class(object): pass >>> keys = [my_inst, my_tuple, my_int, my_complex, my_float, my_string, my_bool, my_unicode, frozenset(my_set), tuple(my_list), my_func, my_class] >>> values = range(12) >>> d = dict(zip(keys, values)) >>> for key, value in d.items(): print key, ":", value 1 : 6 1j : 3 Ham : 7 Spam : 5 (0.0, 1.3999999999999999) : 1 frozenset(['a', 7]) : 8 1.2 : 4 ('a', 7) : 9 <function my_func at 0x0128E7B0> : 10 <class '__main__.my_class'> : 11 <__main__.Hashable object at 0x012AFC50> : 0 >>>
[edit] Raven
[ 'a' 'b' 'c' ] as $keys [ 1 2 3 ] as $vals $keys $vals combine as $hash
[edit] Ruby
keys=['hal',666,[1,2,3]]
vals=['ibm','devil',123]
hash = Hash[*keys.zip(vals).flatten]
# now hash => {'hal' => 'ibm', 666 => 'devil', [1,2,3] => 123}
#retrieve the value linked to the key [1,2,3] puts hash[ [1,2,3] ] #123
[edit] Scala
val keys = Array(1, 2, 3)
val values = Array("A", "B", "C")
val map = Map(keys.zip(values) : _*)
// returns Map(1 -> "A", 2 -> "B", 3 -> "C")
// keys.zip(values) is an array of pairs : Array((1, "A"), (2, "B"), (3, "C"))
// Map(...) expects multiple pairs arguments. Syntax ": _*" tells the single argument contains multiple values.
[edit] Scheme
Using SRFI 69:
(define (lists->hash-table keys values . rest) (apply alist->hash-table (map cons keys values) rest))
[edit] Seed7
$ include "seed7_05.s7i";
const type: numericHash is hash [string] integer;
var numericHash: myHash is numericHash.value;
const proc: main is func
local
var array string: keyList is [] ("one", "two", "three");
var array integer: valueList is [] (1, 2, 3);
var integer: number is 0;
begin
for number range 1 to length(keyList) do
myHash @:= [keyList[number]] valueList[number];
end for;
end func;
[edit] Tcl
Arrays in Tcl are automatically associative, i.e. there are no "not hashed arrays". If we can take "arrays of equal length" to mean "lists of equal length", then the task might look like this:
set keys [list fred bob joe]
set values [list barber plumber tailor]
array set arr {}
foreach a $keys b $values { set $arr($a) $b }
[edit] UnixPipes
Using a sorted file as an associative array (see Creating an associative array for usage.)
cat <<VAL >p.values apple boy cow dog elephant VAL
cat <<KEYS >p.keys a b c d e KEYS
paste -d\ <(cat p.values | sort) <(cat p.keys | sort)

