简体   繁体   中英

Associative arrays (or hash) php to ruby

I'm relatively new to ruby and i came from php. One thing that it seems i would not understand is the difference between hashes and arrays. How do you implement associative arrays in ruby? Eg.

$albums = array();
$songs = array();
$songs[] = array('title' => 'Title 1', 'artist' => 'Artist 1', 'album' => 'Album 1');
$songs[] = array('title' => 'Title 2', 'artist' => 'Artist 2', 'album' => 'Album 2');
$songs[] = array('title' => 'Title 3', 'artist' => 'Artist 1', 'album' => 'Album 1');
$songs[] = array('title' => 'Title 4', 'artist' => 'Artist 1', 'album' => 'Album 1');
$songs[] = array('title' => 'Title 5', 'artist' => 'Artist 3', 'album' => 'Album 1');
foreach($songs as $song)
{
  if( !isset($albums[$song['album']]) ) $albums[$song['album']] = array();
  $albums[$song['album']]['title'] = $song['album'];
  $albums[$song['album']]['songs'] = $song;
}
print_r($albums);
['Album 1']
  => 'title' => 'Album 1'
  => 'songs'
    => 'title' => 'Title 1', 'artist' => 'Artist 1', 'album' => 'Album 1'
    => 'title' => 'Title 3', 'artist' => 'Artist 1', 'album' => 'Album 1'
    => 'title' => 'Title 4', 'artist' => 'Artist 1', 'album' => 'Album 1'
    => 'title' => 'Title 5', 'artist' => 'Artist 3', 'album' => 'Album 1'
['Album 2']
  => 'title' => 'Album 2'
  => 'songs'
    => 'title' => 'Title 1', 'artist' => 'Artist 1', 'album' => 'Album 1'

Or even, instead of title and songs i can declare an array album info with title, artist and how many songs.

How can i do something similar with ruby? what i would use to accomplish that?

A more-or-less direct rewrite from your PHP:

albums = {}
songs = [
  { :title => 'Title 1', :artist => 'Artist 1', :album => 'Album 1' },
  { :title => 'Title 2', :artist => 'Artist 2', :album => 'Album 2' },
  { :title => 'Title 3', :artist => 'Artist 1', :album => 'Album 1' },
  { :title => 'Title 4', :artist => 'Artist 2', :album => 'Album 1' },
  { :title => 'Title 5', :artist => 'Artist 3', :album => 'Album 1' }
]
songs.each do |song|
  album = albums[song[:album]] ||= {}
  album[:title] = song[:title]
  (album[:songs] ||= []).push(song)
end
puts albums.inspect

Easier would be the one-liner:

albums = songs.group_by { |song| song[:album] }

Arrays have only integer keys, and allocate all of them up to the highest one (so if you assign foo[100] = 1 , there will be locations for keys 0-99 also occupying memory (with nil value); you note array values with square brackets: [1, 2, 3] is a 3-element array, [] is empty.

Hashes are enclosed in curly braces {} , and can have pretty much anything as keys. However, blocks can also be written with braces, so take care not to confuse the two.

您应该能够像使用PHP关联数组一样使用Ruby Hash。

As you mentioned in the title of your question, associative arrays are usually referred to as hashes in Ruby. The syntax is slightly different from arrays.

# Normal array
normArray = ["SomeSong", "SomeGuy"]
anotherNormArray = Array.new

# Literal hash
literalHash = { "Title" => "SomeSong", "Artist" => "SomeGuy" }

# Declared beforehand
declaredHash = Hash.new
declaredHash["Songs"] = literalHash

You can do it in one line

songs = [
  {'title' => 'Title 1', 'artist' => 'Artist 1', 'album' => 'Album 1'},
  {'title' => 'Title 2', 'artist' => 'Artist 2', 'album' => 'Album 2'},
  {'title' => 'Title 3', 'artist' => 'Artist 1', 'album' => 'Album 1'},
  {'title' => 'Title 4', 'artist' => 'Artist 1', 'album' => 'Album 1'},
  {'title' => 'Title 5', 'artist' => 'Artist 3', 'album' => 'Album 1'}
]
songs.group_by{|h| h[:album]}.inject({}){|h,(album,s)| h[album] = {:title => album, :songs => s }; h }
#=> {"Album 1"=>{:songs=>[{:artist=>"Artist 1", :album=>"Album 1", :title=>"Title 1"}, {:artist=>"Artist 1", :album=>"Album 1", :title=>"Title 3"}, {:artist=>"Artist 2", :album=>"Album 1", :title=>"Title 4"}, {:artist=>"Artist 3", :album=>"Album 1", :title=>"Title 5"}], :title=>"Album 1"}, "Album 2"=>{:songs=>[{:artist=>"Artist 2", :album=>"Album 2", :title=>"Title 2"}], :title=>"Album 2"}}

Only I don't understand why do you use Album title twice: as a hash key and as a title param? You should use only once, I think :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM