Array of hashes newbie question

Hi all!

I hope this is the right place to ask my question.

I'm trying to get information about my droplets on DigitalOcean.
Information comes as array of hashes:

[{"id"=>1,
   "name"=>"MyTestDroplet",
    "image_id"=>6918990,
    "size_id"=>66,
    "region_id"=>9,
    "backups_active"=>false,
    "ip_address"=>"1.1.1.1",
    "private_ip_address"=>nil,
    "locked"=>false,
    "status"=>"off",
    "created_at"=>"2014-12-08T15:40:09Z"},
  {"id"=>2,
   "name"=>"MyTestDroplet2",
   "image_id"=>6918990,
   "size_id"=>66,
   "region_id"=>7,
   "backups_active"=>false,
   "ip_address"=>"2.2.2.2",
   "private_ip_address"=>nil,
   "locked"=>false,
   "status"=>"off",
   "created_at"=>"2014-12-09T19:27:34Z"}]

My question is how can I get values of specific keys of both hashes?
I need to get information like this:

1
MyTestDroplet
1.1.1.1

2
MyTestDroplet2
2.2.2.2

And number of hashes can be any (as well as number of droplets on
DigitalOcean).

Thank you in advance!

···

--
Best regards,
Pavel "Che" Letskiy

Assuming you place the array in a variable called droplets

droplets.each { |droplet|
  puts droplet['id']
  puts droplet['name']
  puts droplet['ip_address']
}

John

hash.map{|h| h[‘name’]}

···

On Dec 9, 2014, at 15:00, Paul Letskiy <letskiy@gmail.com> wrote:

Hi all!

I hope this is the right place to ask my question.

I'm trying to get information about my droplets on DigitalOcean. Information comes as array of hashes:

[{"id"=>1,
   "name"=>"MyTestDroplet",
    "image_id"=>6918990,
    "size_id"=>66,
    "region_id"=>9,
    "backups_active"=>false,
    "ip_address"=>"1.1.1.1",
    "private_ip_address"=>nil,
    "locked"=>false,
    "status"=>"off",
    "created_at"=>"2014-12-08T15:40:09Z"},
  {"id"=>2,
   "name"=>"MyTestDroplet2",
   "image_id"=>6918990,
   "size_id"=>66,
   "region_id"=>7,
   "backups_active"=>false,
   "ip_address"=>"2.2.2.2",
   "private_ip_address"=>nil,
   "locked"=>false,
   "status"=>"off",
   "created_at"=>"2014-12-09T19:27:34Z"}]

My question is how can I get values of specific keys of both hashes?
I need to get information like this:

1
MyTestDroplet
1.1.1.1

2
MyTestDroplet2
2.2.2.2

Thank you! It works!

···

2014-12-09 23:02 GMT+03:00 Bryce Kerley <bkerley@brycekerley.net>:

On Dec 9, 2014, at 15:00, Paul Letskiy <letskiy@gmail.com> wrote:
>
> Hi all!
>
> I hope this is the right place to ask my question.
>
> I'm trying to get information about my droplets on DigitalOcean.
Information comes as array of hashes:
>
> [{"id"=>1,
> "name"=>"MyTestDroplet",
> "image_id"=>6918990,
> "size_id"=>66,
> "region_id"=>9,
> "backups_active"=>false,
> "ip_address"=>"1.1.1.1",
> "private_ip_address"=>nil,
> "locked"=>false,
> "status"=>"off",
> "created_at"=>"2014-12-08T15:40:09Z"},
> {"id"=>2,
> "name"=>"MyTestDroplet2",
> "image_id"=>6918990,
> "size_id"=>66,
> "region_id"=>7,
> "backups_active"=>false,
> "ip_address"=>"2.2.2.2",
> "private_ip_address"=>nil,
> "locked"=>false,
> "status"=>"off",
> "created_at"=>"2014-12-09T19:27:34Z"}]
>
>
> My question is how can I get values of specific keys of both hashes?
> I need to get information like this:
>
> 1
> MyTestDroplet
> 1.1.1.1
>
> 2
> MyTestDroplet2
> 2.2.2.2

hash.map{|h| h[‘name’]}

--
С уважением,
Павел "Che" Лецкий

It works only with arrays, as I understand.
With array of hashes I get an error:

no implicit conversion of String into Integer (TypeError)

···

2014-12-09 23:04 GMT+03:00 John W Higgins <wishdev@gmail.com>:

Assuming you place the array in a variable called droplets

droplets.each { |droplet|
  puts droplet['id']
  puts droplet['name']
  puts droplet['ip_address']
}

John

--
С уважением,
Павел "Che" Лецкий

irb2.1.5> droplets.map {|h| h.values_at('id', 'name', 'ip_address')}
#2.1.5 => [[1, "MyTestDroplet", "1.1.1.1"], [2, "MyTestDroplet2", "2.2.2.2"]]

You can learn more about Array#map (actually Enumerable#map) and Hash#values_at from the documentation:

From APIdock.com
http://apidock.com/ruby/Array/map
http://apidock.com/ruby/Hash/values_at

or from Ruby-Lang.org

-Rob

···

On 2014-Dec-9, at 15:10 , Paul Letskiy <letskiy@gmail.com> wrote:

It works only with arrays, as I understand.
With array of hashes I get an error:

no implicit conversion of String into Integer (TypeError)

2014-12-09 23:04 GMT+03:00 John W Higgins <wishdev@gmail.com>:
Assuming you place the array in a variable called droplets

droplets.each { |droplet|
  puts droplet['id']
  puts droplet['name']
  puts droplet['ip_address']
}

John
--
С уважением,
Павел "Che" Лецкий

Hi,

It works only with arrays, as I understand.

You can iterate through Arrays or Hashes depends on the situation. In your case you have an ‘Array’ of ‘Hashes’. A very common pattern in ruby. So first you need to iterate through the Array, then you can work with each entry of the array, which is your case is a Hash object. Here is another code sample (simpler tho read IMHO the the other ones):

#!/usr/bin/env ruby

droplets = [{"id"=>1,
            "name"=>"MyTestDroplet",
            "image_id"=>6918990,
            "size_id"=>66,
            "region_id"=>9,
            "backups_active"=>false,
            "ip_address"=>"1.1.1.1",
            "private_ip_address"=>nil,
            "locked"=>false,
            "status"=>"off",
            "created_at"=>"2014-12-08T15:40:09Z"},
            {"id"=>2,
             "name"=>"MyTestDroplet2",
             "image_id"=>6918990,
             "size_id"=>66,
             "region_id"=>7,
             "backups_active"=>false,
             "ip_address"=>"2.2.2.2",
             "private_ip_address"=>nil,
             "locked"=>false,
             "status"=>"off",
             "created_at"=>"2014-12-09T19:27:34Z"}]

# p droplets.class # => Array
# p droplets[0].class # => Hash

counter = 1

# Iterate through Array entries here
droplets.each do |entry|
  # Now 'entry' is a hash.
  # We access hash values by requesting 'keys'
  puts ""
  puts "Entry: #{counter}"
  puts entry["name"] # => MyTestDroplet ...
  puts entry["image_id"] # => 6918990
  puts "-"*3
  counter += 1
end

Just a note about the use of a separate counter variable.

irb2.1.5> array = %w[ a b c d e ]
#2.1.5 => ["a", "b", "c", "d", "e"]

Array#each gives you one element at a time:

irb2.1.5> array.each {|element| puts "#{element}" }; nil
a
b
c
d
e

If you need the array index of the element, you can use the #with_index method:

irb2.1.5> array.each.with_index {|element, index| puts "#{index}: #{element}" }; nil
0: a
1: b
2: c
3: d
4: e

Which is 0-based by default, but you can also provide an initial value:

irb2.1.5> array.each.with_index(1) {|element, index| puts "#{index}: #{element}" }; nil
1: a
2: b
3: c
4: d
5: e

which is exactly your counter.

droplets.each.with_index(1) do |entry, counter|
  # puts various things
end

-Rob

···

On 2014-Dec-9, at 16:01 , Panagiotis Atmatzidis <atma@convalesco.org> wrote:

On 9 Dec 2014, at 22:10, Paul Letskiy <letskiy@gmail.com> wrote:

With array of hashes I get an error:

no implicit conversion of String into Integer (TypeError)

What kind of code gives you this error? Can you show us your snippet?

best regards

Panagiotis (atmosx) Atmatzidis

email: atma@convalesco.org
URL: http://www.convalesco.org
GnuPG ID: 0x1A7BFEC5
gpg --keyserver pgp.mit.edu --recv-keys 1A7BFEC5

"As you set out for Ithaca, hope the voyage is a long one, full of adventure, full of discovery [...]" - C. P. Cavafy

Hi,

It works only with arrays, as I understand.

You can iterate through Arrays or Hashes depends on the situation. In your case you have an ‘Array’ of ‘Hashes’. A very common pattern in ruby. So first you need to iterate through the Array, then you can work with each entry of the array, which is your case is a Hash object. Here is another code sample (simpler tho read IMHO the the other ones):

#!/usr/bin/env ruby

droplets = [{"id"=>1,
            "name"=>"MyTestDroplet",
            "image_id"=>6918990,
            "size_id"=>66,
            "region_id"=>9,
            "backups_active"=>false,
            "ip_address"=>"1.1.1.1",
            "private_ip_address"=>nil,
            "locked"=>false,
            "status"=>"off",
            "created_at"=>"2014-12-08T15:40:09Z"},
            {"id"=>2,
             "name"=>"MyTestDroplet2",
             "image_id"=>6918990,
             "size_id"=>66,
             "region_id"=>7,
             "backups_active"=>false,
             "ip_address"=>"2.2.2.2",
             "private_ip_address"=>nil,
             "locked"=>false,
             "status"=>"off",
             "created_at"=>"2014-12-09T19:27:34Z"}]

# p droplets.class # => Array
# p droplets[0].class # => Hash

counter = 1

# Iterate through Array entries here
droplets.each do |entry|
  # Now 'entry' is a hash.
  # We access hash values by requesting 'keys'
  puts ""
  puts "Entry: #{counter}"
  puts entry["name"] # => MyTestDroplet ...
  puts entry["image_id"] # => 6918990
  puts "-"*3
  counter += 1
end

With array of hashes I get an error:

no implicit conversion of String into Integer (TypeError)

What kind of code gives you this error? Can you show us your snippet?

best regards

Panagiotis (atmosx) Atmatzidis

email: atma@convalesco.org
URL: http://www.convalesco.org
GnuPG ID: 0x1A7BFEC5
gpg --keyserver pgp.mit.edu --recv-keys 1A7BFEC5

"As you set out for Ithaca, hope the voyage is a long one, full of adventure, full of discovery [...]" - C. P. Cavafy

···

On 9 Dec 2014, at 22:10, Paul Letskiy <letskiy@gmail.com> wrote:

Oh, thanks for the pointer Rob. Using ‘with_index’ like that never occurred to me. Admittedly it looks much cleaner!

Panagiotis (atmosx) Atmatzidis

email: atma@convalesco.org
URL: http://www.convalesco.org
GnuPG ID: 0x1A7BFEC5
gpg --keyserver pgp.mit.edu --recv-keys 1A7BFEC5

"As you set out for Ithaca, hope the voyage is a long one, full of adventure, full of discovery [...]" - C. P. Cavafy

···

On 10 Dec 2014, at 00:01, Rob Biedenharn <rob.biedenharn@gmail.com> wrote:

On 2014-Dec-9, at 16:01 , Panagiotis Atmatzidis <atma@convalesco.org <mailto:atma@convalesco.org>> wrote:

Hi,

On 9 Dec 2014, at 22:10, Paul Letskiy <letskiy@gmail.com <mailto:letskiy@gmail.com>> wrote:

It works only with arrays, as I understand.

You can iterate through Arrays or Hashes depends on the situation. In your case you have an ‘Array’ of ‘Hashes’. A very common pattern in ruby. So first you need to iterate through the Array, then you can work with each entry of the array, which is your case is a Hash object. Here is another code sample (simpler tho read IMHO the the other ones):

#!/usr/bin/env ruby

droplets = [{"id"=>1,
            "name"=>"MyTestDroplet",
            "image_id"=>6918990,
            "size_id"=>66,
            "region_id"=>9,
            "backups_active"=>false,
            "ip_address"=>"1.1.1.1",
            "private_ip_address"=>nil,
            "locked"=>false,
            "status"=>"off",
            "created_at"=>"2014-12-08T15:40:09Z"},
            {"id"=>2,
             "name"=>"MyTestDroplet2",
             "image_id"=>6918990,
             "size_id"=>66,
             "region_id"=>7,
             "backups_active"=>false,
             "ip_address"=>"2.2.2.2",
             "private_ip_address"=>nil,
             "locked"=>false,
             "status"=>"off",
             "created_at"=>"2014-12-09T19:27:34Z"}]

# p droplets.class # => Array
# p droplets[0].class # => Hash

counter = 1

# Iterate through Array entries here
droplets.each do |entry|
  # Now 'entry' is a hash.
  # We access hash values by requesting 'keys'
  puts ""
  puts "Entry: #{counter}"
  puts entry["name"] # => MyTestDroplet ...
  puts entry["image_id"] # => 6918990
  puts "-"*3
  counter += 1
end

Just a note about the use of a separate counter variable.

irb2.1.5> array = %w[ a b c d e ]
#2.1.5 => ["a", "b", "c", "d", "e"]

Array#each gives you one element at a time:

irb2.1.5> array.each {|element| puts "#{element}" }; nil
a
b
c
d
e

If you need the array index of the element, you can use the #with_index method:

irb2.1.5> array.each.with_index {|element, index| puts "#{index}: #{element}" }; nil
0: a
1: b
2: c
3: d
4: e

Which is 0-based by default, but you can also provide an initial value:

irb2.1.5> array.each.with_index(1) {|element, index| puts "#{index}: #{element}" }; nil
1: a
2: b
3: c
4: d
5: e

which is exactly your counter.

droplets.each.with_index(1) do |entry, counter|
  # puts various things
end

-Rob