Ассоциативные массивы (или хэш) php на ruby - PullRequest
1 голос
/ 26 апреля 2011

Я относительно новичок в ruby ​​и пришел из php. Одна вещь, которую, кажется, я бы не понял, это разница между хэшами и массивами. Как вы реализуете ассоциативные массивы в ruby? Например.

$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'

Или даже вместо названия и песен я могу объявить информацию об альбоме массива с названием, исполнителем и количеством песен.

Как мне сделать что-то похожее с ruby? что бы я использовал для этого?

Ответы [ 4 ]

4 голосов
/ 26 апреля 2011

Более или менее прямая перезапись с вашего 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

Проще было бы однострочно:

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

Массивы имеют только целочисленные ключи и выделяют всеиз них вплоть до самого высокого (поэтому, если вы назначите foo[100] = 1, будут места для ключей 0-99, также занимающих память (со значением nil); вы отметите значения массива в квадратных скобках: [1, 2, 3] представляет собой 3-элементный массив, [] пуст.

Хэши заключены в фигурные скобки {} и могут содержать почти все что угодно в качестве ключей. Однако блоки также могут быть записаны с фигурными скобками, поэтому будьте осторожны, чтобыпутать два.

2 голосов
/ 26 апреля 2011

Как вы упомянули в заголовке вашего вопроса, в Ruby ассоциативные массивы обычно называются хешами.Синтаксис немного отличается от массивов.

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

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

# Declared beforehand
declaredHash = Hash.new
declaredHash["Songs"] = literalHash
2 голосов
/ 26 апреля 2011

Вы можете сделать это в одной строке

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"}}

Только я не понимаю, почему вы используете название альбома дважды: в качестве ключа хеша и в качестве параметра заголовка?Вы должны использовать только один раз, я думаю:)

2 голосов
/ 26 апреля 2011

Вы должны иметь возможность использовать Ruby Hash точно так же, как ассоциативный массив PHP.

...