2012-06-08 31 views
5

Tengo una simple matriz¿Convertir una matriz de tuplas de Ruby en un hash con una matriz de claves?

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

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

¿Cómo puedo convertir a este hash cada vez que los elementos de matriz coincide con el primer elemento de cada elemento en matriz2?

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

Soy bastante nuevo en el rubí, y paso mucho que hacer esta manipulación, pero no hubo suerte, alguna ayuda?

+0

¿Qué quiere decir exactamente por "coincidir con el primer elemento de cada elemento en matriz2"? – Mischa

+4

No edite mi respuesta, deje un comentario – Mischa

Respuesta

10

Si el orden de la correspondencia entre la llave y pares debe basarse en el primer elemento de array2, entonces no es necesario en absoluto array:

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"] 
#=> } 

Si desea utilizar array para seleccionar un subconjunto de elementos, entonces usted puede hacer esto:

# 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"] 
#=> } 

El código if map.key?(val) y compact garantiza que no hay ningún problema si array solicita claves que no están presentes en array2, y lo hace en O(n) time.

+0

Esto no tiene en cuenta el siguiente requisito: "siempre que el elemento en la matriz coincida con el primer elemento de cada elemento en la matriz2". – Mischa

+0

@Mischa Lo hace ahora. :) – Phrogz

2

Esto le da el resultado deseado.

hash = {} 

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

Hola, gracias, ¿qué pasa si array2 no está en orden? –

+1

Bueno, eso no está claro en tu pregunta. La próxima vez, refleja más claramente lo que quieres en tu ejemplo. ¿Pueden 'apple',' orange' y 'lemon' aparecer más de una vez en' array2', en caso afirmativo, ¿cómo desea que se vea el hash resultante? Por favor actualice su pregunta con un ejemplo claro y un resultado esperado. – Mischa

+0

@KitHo, esto funciona si la matriz no está en orden. – Mischa

-1

ohh..I tentados para anular rassoc

revisa el siguiente en la 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 
Cuestiones relacionadas