2012-06-08 4 views
5

У меня есть простой массивПреобразование массива блоков Ruby в хэш задает массив ключей?

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

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

как я могу преобразовать в эту хэш всякий раз, когда элемент массива соответствует первый элемент каждого элемента в массив2?

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

Я совершенно новой для рубина, и тратить много, чтобы сделать эту манипуляцию, но не повезло, какой-либо помощи?

+0

Что вы точно подразумеваем под «сопрягать первый элемент каждого элемента в массив2»? – Mischa

+4

Не изменяйте мой ответ, оставьте комментарий – Mischa

ответ

10

Если порядок отображения между ключом и пар должен быть основан на первом элементе в array2, то вам не нужно 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"] 
#=> } 

Если вы хотите использовать array для выбора подмножества элементов, то вы можете сделать это:

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

код if map.key?(val) и compact гарантирует, что нет проблем, если array запрашивает ключи, которых нет в array2, и делает это в O(n) времени.

+0

Это не учитывает следующее требование: «всякий раз, когда элемент в массиве соответствует первому элементу каждого элемента в массиве2». – Mischa

+0

@Mischa Теперь. :) – Phrogz

2

Это дает вам желаемый результат.

hash = {} 

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

Привет, THX, а как насчет того, если array2 не в порядке? –

+1

Ну, это не ясно из вашего вопроса. В следующий раз более четко отразите то, что вы хотите в своем примере. Если '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ', то если вы хотите, чтобы получившийся хэш выглядел. Пожалуйста, обновите свой вопрос с ясного примера и ожидаемого результата. – Mischa

+0

@KitHo, это работает, если массив не в порядке. – Mischa

-1

ohh..I соблазн переопределить rassoc

проверьте следующее на 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 
Смежные вопросы