2012-06-08 5 views
5

Ich habe ein einfaches ArrayKonvertieren Ruby Array von Tupeln in einen Hash bei einem Array von Schlüsseln?

array = ["apple", "orange", "lemon"] 

array2 = [["apple", "good taste", "red"], ["orange", "bad taste", "orange"], ["lemon" , "no taste", "yellow"]] 

wie ich auf diese Hash konvertieren kann, wann immer in Element in dem Array das erste Element in array2 jedes Elements überein?

hash = {"apple" => ["apple" ,"good taste", "red"], 
     "orange" => ["orange", "bad taste", "orange"], 
     "lemon" => ["lemon" , "no taste", "yellow"] } 

Ich bin ziemlich neu zu Rubin, und verbringen viel, um diese Manipulation zu tun, aber kein Glück, keine Hilfe?

+0

Was meinen Sie genau mit "entsprechen das erste Element jedes Elements in array2" außer Kraft zu setzen versucht? – Mischa

+4

Bearbeiten Sie meine Antwort nicht, hinterlassen Sie einen Kommentar – Mischa

Antwort

10

Wenn die Reihenfolge der Zuordnung zwischen Schlüssel und Paare sollten in array2 auf dem ersten Element basieren, dann brauchen Sie nicht array überhaupt:

array2 = [ 
    ["apple", "good taste", "red"], 
    ["lemon" , "no taste", "yellow"], 
    ["orange", "bad taste", "orange"] 
] 

map = Hash[ array2.map{ |a| [a.first,a] } ] 
p map 
#=> { 
#=> "apple"=>["apple", "good taste", "red"], 
#=> "lemon"=>["lemon", "no taste", "yellow"], 
#=> "orange"=>["orange", "bad taste", "orange"] 
#=> } 

Wenn Sie verwenden möchten, array eine Teilmenge von Elementen zu wählen, dann können Sie dies tun:

# Use the map created above to find values efficiently 
array = %w[orange lemon] 
hash = Hash[ array.map{ |val| [val,map[val]] if map.key?(val) }.compact ] 
p hash 
#=> { 
#=> "orange"=>["orange", "bad taste", "orange"], 
#=> "lemon"=>["lemon", "no taste", "yellow"] 
#=> } 

der Code if map.key?(val) und compact stellt sicher, dass es kein Problem gibt, wenn array nach Schlüsseln fragt, die in array2 nicht vorhanden sind, und zwar in O(n) Zeit.

+0

Dies berücksichtigt nicht die folgende Anforderung: "Immer wenn Element in Array mit dem ersten Element jedes Elements in Array2 übereinstimmt". – Mischa

+0

@Mischa Es tut jetzt. :) – Phrogz

2

Dies bringt Ihnen das gewünschte Ergebnis.

hash = {} 

array.each do |element| 
    i = array2.index{ |x| x[0] == element } 
    hash[element] = array2[i] unless i.nil? 
end 
+0

Hi, thx, was ist, wenn Array2 nicht in Ordnung ist? –

+1

Nun, das ist nicht klar aus Ihrer Frage. Das nächste Mal widerspiegelt, was Sie in Ihrem Beispiel deutlicher sehen. Können 'apple',' orange' und 'lemon' mehr als einmal in' array2' vorkommen, wenn ja, wie soll der resultierende Hash aussehen? Bitte aktualisieren Sie Ihre Frage mit einem klaren Beispiel und einer erwarteten Ausgabe. – Mischa

+0

@KitHo, das funktioniert, wenn das Array nicht in Ordnung ist. – Mischa

-1

ohh..I rassoc

Schauen Sie sich die folgenden auf irb

class Array 
    def rassoc obj, place=1 
    if place 
     place = place.to_i rescue -1 
     return if place < 0 
    end 

    self.each do |item| 
     next unless item.respond_to? :include? 

     if place 
     return item if item[place]==obj 
     else 
     return item if item.include? obj 
     end 
    end 

    nil 
    end 
end 

array = ["apple", "orange", "lemon"] 
array2 = [["apple", "good taste", "red"], ["orange", "bad taste", "orange"], ["lemon" , "no taste", "yellow"]] 

Hash[ array.map{ |fruit| [fruit, array2.rassoc(fruit, nil)]}] 
# this is what you want 

# order changed 
array2 = [["good taste", "red", "apple"], ["no taste", "lemon", "yellow"], ["orange", "bad taste", "orange"]] 

Hash[ array.map{ |fruit| [fruit, array2.rassoc(fruit, nil)]}] 
# same what you want after order is changed 
Verwandte Themen