Creating a hash from two arrays

Hi. Can anyone help with this? I'd like to end with a hash like so:

hash = {{"A" => 'alpha'}, {'B' => 'bravo'}} etc...

I'm not sure whether I can use group_by and how to handle case
insensitity. Cheers for any help.

irb(main):001:0> s = ('A'..'Z').to_a
=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]

irb(main):003:0> t = %w(alpha bravo Charlie Zebra)
=> ["alpha", "bravo", "Charlie", "Zebra"]

···

--
Posted via http://www.ruby-forum.com/.

Hi. Can anyone help with this? I'd like to end with a hash like so:

hash = {{"A" => 'alpha'}, {'B' => 'bravo'}} etc...

I'm not sure whether I can use group_by and how to handle case
insensitity. Cheers for any help.

irb(main):001:0> s = ('A'..'Z').to_a
=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]

irb(main):003:0> t = %w(alpha bravo Charlie Zebra)
=> ["alpha", "bravo", "Charlie", "Zebra"]

I will suggest something different based on what you wish to do. This uses inject:
---t = %w(alpha bravo Charlie Zebra)
result = t.inject(Hash.new) do | words, word | first_letter = word[0].upcase words[first_letter] = word wordsend---
result looks like this:
{"A"=>"alpha", "B"=>"bravo", "C"=>"Charlie", "Z"=>"Zebra"}
Now, if there's a chance that words with start with the letter A, or any other letter might occur, I instead recommend an array based approach:
---t = %w(alpha bravo Charlie Zebra)
result = t.inject(Hash.new) do | words,word | first_letter = word[0].upcase if words.has_key? first_letter words[first_letter] << word else words[first_letter] = [word] end wordsend---
result produces:
{"A"=>["alpha"], "B"=>["bravo"], "C"=>["Charlie"], "Z"=>["Zebra"]}
In both cases, the first letter is uppercased to handle being case insensitive. Let me know if you have any questions regarding this, or if you have a different problem you are trying to solve.
Best Regards,Chris White

Funny, I just looked this up yesterday:

···

On Fri, Sep 9, 2011 at 9:51 AM, simon harrison <simonharrison.uk@gmail.com>wrote:

Hi. Can anyone help with this? I'd like to end with a hash like so:

hash = {{"A" => 'alpha'}, {'B' => 'bravo'}} etc...

I'm not sure whether I can use group_by and how to handle case
insensitity. Cheers for any help.

irb(main):001:0> s = ('A'..'Z').to_a
=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]

irb(main):003:0> t = %w(alpha bravo Charlie Zebra)
=> ["alpha", "bravo", "Charlie", "Zebra"]

--
Posted via http://www.ruby-forum.com/\.

Hi. Can anyone help with this? I'd like to end with a hash like so:

hash = {{"A" => 'alpha'}, {'B' => 'bravo'}} etc...

I'm not sure whether I can use group_by and how to handle case
insensitity. Cheers for any help.

irb(main):001:0> s = ('A'..'Z').to_a
=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]

irb(main):003:0> t = %w(alpha bravo Charlie Zebra)
=> ["alpha", "bravo", "Charlie", "Zebra"]

First, {{"A" => "alpha"}, {"B" => "bravo"}} isn't valid syntax. You
probably meant:

{"A" => "alpha", "B" => "bravo", ...}

?

You can indeed use group_by:

(("A".."C").to_a + ("a".."c").to_a).group_by { |e| e[0, 1].downcase }

=> {"a"=>["A", "a"], "b"=>["B", "b"], "c"=>["C", "c"]}

Alternatively, if you want to simply map from a[i] to b[i] in a hash,
you can use #zip, #flatten and a splat, in combination with Hash.:

a = %w[a b c d e]; b = (1..5)

c = a.zip(b)

=> [["a", 1], ["b", 2], ["c", 3], ["d", 4], ["e", 5]]

c.flatten!

=> ["a", 1, "b", 2, "c", 3, "d", 4, "e", 5]

Hash[*c] # equivalent to Hash["a", 1, "b", 2, ...]

=> {"a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5}

Or, in one go:

Hash[*a.zip(b).flatten]

=> {"a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5}

Zip, flatten, splat.

This obviously won't let you store multiple elements ("a" => ["a",
"A"]) as in the above approach.

···

On Fri, Sep 9, 2011 at 5:51 PM, simon harrison <simonharrison.uk@gmail.com> wrote:

Thanks for all the help. I knew about zip but as both arrays have to
have the same number of elements it doesn't help in this case. Two more
questions:

1. Are there any tutorials/blog posts explaining converting arrays to
hashes and using inject?

2. My real aim is to move files/directories into A-Z directories. I'm
also interested in the general principles for copying values that are
common from different structures to another structure. Any tutorials for
that sort of thing?

Cheers again.

···

--
Posted via http://www.ruby-forum.com/.

Robert, I seem to remember that it was you who said you'd implemented
all the Enumerable module using inject. Any chance of having a look at
that code?

···

--
Posted via http://www.ruby-forum.com/.

Date: Sat, 10 Sep 2011 02:05:15 +0900
From: cwprogram@live.com
Subject: Re: Creating a hash from two arrays
To: ruby-talk@ruby-lang.org

> Hi. Can anyone help with this? I'd like to end with a hash like so:
>
> hash = {{"A" => 'alpha'}, {'B' => 'bravo'}} etc...
>
>
>
> I'm not sure whether I can use group_by and how to handle case
> insensitity. Cheers for any help.
>
>
>
> irb(main):001:0> s = ('A'..'Z').to_a
> => ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
> "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
>
> irb(main):003:0> t = %w(alpha bravo Charlie Zebra)
> => ["alpha", "bravo", "Charlie", "Zebra"]

My message got garbled for some reason.... Here is the gist: Character Mapping · GitHub

This works in 1.9 at least.

If both arrays are the same size, you can use Array.zip and Hash[] like this:

irb(main):001:0> alpha = ('A'..'Z').to_a
=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
irb(main):002:0> ansi = %w{Alpha Bravo Charlie Delta Echo Foxtrot Golf
Hotel India Juliet Kilo Lima Mike November Oscar Papa Quebec Romeo
Sierra Tango Uniform Victor Whiskey X-ray Yankee Zulu}
=> ["Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf",
"Hotel", "India", "Juliet", "Kilo", "Lima", "Mike", "November",
"Oscar", "Papa", "Quebec", "Romeo", "Sierra", "Tango", "Uniform",
"Victor", "Whiskey", "X-ray", "Yankee", "Zulu"]
irb(main):003:0> alpha.size
=> 26
irb(main):004:0> ansi.size
=> 26
irb(main):005:0> alpha.zip(ansi)
=> [["A", "Alpha"], ["B", "Bravo"], ["C", "Charlie"], ["D", "Delta"],
["E", "Echo"], ["F", "Foxtrot"], ["G", "Golf"], ["H", "Hotel"], ["I",
"India"], ["J", "Juliet"], ["K", "Kilo"], ["L", "Lima"], ["M",
"Mike"], ["N", "November"], ["O", "Oscar"], ["P", "Papa"], ["Q",
"Quebec"], ["R", "Romeo"], ["S", "Sierra"], ["T", "Tango"], ["U",
"Uniform"], ["V", "Victor"], ["W", "Whiskey"], ["X", "X-ray"], ["Y",
"Yankee"], ["Z", "Zulu"]]
irb(main):006:0> zippedhash = Hash[alpha.zip(ansi)]
=> {"A"=>"Alpha", "B"=>"Bravo", "C"=>"Charlie", "D"=>"Delta",
"E"=>"Echo", "F"=>"Foxtrot", "G"=>"Golf", "H"=>"Hotel", "I"=>"India",
"J"=>"Juliet", "K"=>"Kilo", "L"=>"Lima", "M"=>"Mike", "N"=>"November",
"O"=>"Oscar", "P"=>"Papa", "Q"=>"Quebec", "R"=>"Romeo", "S"=>"Sierra",
"T"=>"Tango", "U"=>"Uniform", "V"=>"Victor", "W"=>"Whiskey",
"X"=>"X-ray", "Y"=>"Yankee", "Z"=>"Zulu"}

SUMMARY:

  new_hash = Hash[array1.zip(array2)]

Quick-and-easy so long as array1 and array2 are equal length.

Aaron out.

I wouldn't use inject ! You aren't really reducing something down to
one element, you're converting a mapping which exists based on an
index into an actual hash. Aside from that, the group_by is much
easier to comprehend quickly than the inject approach in your second
example.

···

On Fri, Sep 9, 2011 at 6:05 PM, Chris White <cwprogram@live.com> wrote:

I will suggest something different based on what you wish to do. This uses inject:

Currently I have no idea where that code went. :slight_smile: If I dig it up I'll post it.

Kind regards

robert

···

On Mon, Sep 12, 2011 at 7:05 PM, simon harrison <simonharrison.uk@gmail.com> wrote:

Robert, I seem to remember that it was you who said you'd implemented
all the Enumerable module using inject. Any chance of having a look at
that code?

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Ah, yes, this works without the splat, too. I seem to remember that
this doesn't work on 1.8(.7?), which is when I learned it.

···

On Fri, Sep 9, 2011 at 6:15 PM, Aaron D. Gifford <astounding@gmail.com> wrote:

SUMMARY:

new_hash = Hash[array1.zip(array2)]

Why would anyone do that is beyond me.

:frowning:

-- Matma Rex

···

2011/9/12 Robert Klemme <shortcutter@googlemail.com>:

On Mon, Sep 12, 2011 at 7:05 PM, simon harrison > <simonharrison.uk@gmail.com> wrote:

Robert, I seem to remember that it was you who said you'd implemented
all the Enumerable module using inject. Any chance of having a look at
that code?

Currently I have no idea where that code went. :slight_smile: If I dig it up I'll post it.

Or using just the list of words and Ruby 1.9:

  ansi = %w{Alpha Bravo Charlie Delta ...... Zulu}
  zippedhash = Hash[ansi.map{|x| x[0].downcase}.zip(ansi)]

@Adam Prescott, I think you're right about 1.8, which is why I
prefaced my response with "This works in 1.9 at least." *chuckle*

Aaron out.

Well, I am trying to be kind and provide the information I have. I
cannot find anything strange about that.

Cheers

robert

···

2011/9/13 Bartosz Dziewoński <matma.rex@gmail.com>:

2011/9/12 Robert Klemme <shortcutter@googlemail.com>:

On Mon, Sep 12, 2011 at 7:05 PM, simon harrison >> <simonharrison.uk@gmail.com> wrote:

Robert, I seem to remember that it was you who said you'd implemented
all the Enumerable module using inject. Any chance of having a look at
that code?

Currently I have no idea where that code went. :slight_smile: If I dig it up I'll post it.

Why would anyone do that is beyond me.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

:wink:

or - avoiding the temporary Array:

ansi = %w{Alpha Bravo Charlie Delta ...... Zulu}
hash = {}
ansi.each {|w| hash[w[0].upcase] = w}

Kind regards

robert

···

On Fri, Sep 9, 2011 at 7:24 PM, Aaron D. Gifford <astounding@gmail.com> wrote:

Or using just the list of words and Ruby 1.9:

ansi = %w{Alpha Bravo Charlie Delta ...... Zulu}
zippedhash = Hash[ansi.map{|x| x[0].downcase}.zip(ansi)]

@Adam Prescott, I think you're right about 1.8, which is why I
prefaced my response with "This works in 1.9 at least." *chuckle*

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/