2011-01-01 11 views
20

Hier ist meine Situation. Ich habe 2 ArraysRuby zwei Arrays zu einem zusammenführen

@names = ["Tom", "Harry", "John"] 

@emails = ["[email protected]", "[email protected]", "[email protected]"] 

ich diese beiden in eine Array/Hash kombinieren möchten genannt @list so kann ich dann meiner Meinung nach so etwas wie dieses iterieren:

<% @list.each do |item| %> 
<%= item.name %><br> 
<%= item.email %><br> 
<% end %> 

Ich habe Probleme zu verstehen, wie Ich kann dieses Ziel erreichen. Irgendwelche Gedanken?

Antwort

46
@names = ["Tom", "Harry", "John"] 
@emails = ["[email protected]", "[email protected]", "[email protected]"] 

@list = @names.zip(@emails) 
#=> [["Tom", "[email protected]"], ["Harry", "[email protected]"], ["John", "[email protected]"]] 

@list.each do |name,email| 
    # When a block is passed an array you can automatically "destructure" 
    # the array parts into named variables. Yay for Ruby! 
    p "#{name} <#{email}>" 
end 
#=> "Tom <[email protected]>" 
#=> "Harry <[email protected]>" 
#=> "John <[email protected]>" 

@urls = ["yahoo.com", "ebay.com", "google.com"] 

# Zipping multiple arrays together 
@names.zip(@emails, @urls).each do |name,email,url| 
    p "#{name} <#{email}> :: #{url}" 
end 
#=> "Tom <[email protected]> :: yahoo.com" 
#=> "Harry <[email protected]> :: ebay.com" 
#=> "John <[email protected]> :: google.com" 
+4

Aha! Also * das * ist was 'zip' ist für! Es kam irgendwie nie wirklich in meine Standard-Toolbox. Nett. +1 – Matchu

+0

Wäre diese Lösung noch anwendbar, fügte ich eine andere Instanzvariable namens @urls = ["yahoo.com", "ebay.com", "google.com"] hinzu. – lou1221

+0

@ lou1221 Ja; Siehe die aktualisierte Antwort oben. 'Array # zip' kann eine beliebige Anzahl von Argumenten annehmen. – Phrogz

3

können Sie zip verwenden, um die beiden Arrays zip zusammen und map dann Item Objekte aus den Namen-E-Mail-Paare zu erstellen. Angenommen, Sie haben eine Item Klasse, deren initialize Methoden akzeptiert einen Hash, aussehen würde der Code wie folgt:

@list = @names.zip(@emails).map do |name, email| 
    Item.new(:name => name, :email => email) 
end 
7
Hash[*names.zip(emails).flatten] 

Dies gibt Ihnen einen Hash mit name => E-Mail.

+1

Funktioniert für diese Situation, aber zukünftige Leser aufpassen: es ist keine allgemeine Lösung, da, wenn entweder 'names' oder' emails' Arrays mit Arrays wären, 'flatten' rekursiv ausgeführt würde. – Matchu

+5

Unter Ruby 1.9 können Sie einfach tun: 'Hash [Names.zip (E-Mails)]' – Phrogz

+2

flatten (1) verhindert Rekursion, falls gewünscht. –

15

einfach anders zu sein:

[@names, @emails, @urls].transpose.each do |name, email, url| 
    # . . . 
end 

Dies ähnelt, was Array#zip tut, außer dass in diesem Fall wird es keine Null-Polsterung von kurzen Reihen sein; Wenn etwas fehlt, wird eine Ausnahme ausgelöst.

+5

Der Tipp auf Transpose ist groß. Danke für das Posten dieses – lou1221

+1

Ich suchte nach Pythons 'zip (* arrays)'. Das ist es! – Droogans

3

Diese

Hash[@names.zip(@emails)] 

Sie haben zwei Arrays @names = [ "Tom", "Harry", "John"]

@emails = [ "[email protected]" Versuchen Sie, "[email protected]", "[email protected]"]

@ names.zip (@emails) es merge @emails zu den @Names zusammen, die mit ihrem Index wie unten verbunden sind [["Tom", ""] [email protected] "], [" Harry "," [email protected] "], [" John "," [email protected] "]]

Jetzt können wir dieses Array in Hash konvertieren mit Hash [@ Names.zip (@emails)]

Verwandte Themen