2015-07-13 9 views
5

Czy jest łatwiejsza transpozycja następującego skrótu? Mam rozwiązanie, które działa, ale metoda transpozycji jest trudna do odczytania. Przypadek użycia to skrót zadań (j1, j2, j3 itd.) Oraz daty, w których występują (d1, d2, d3 itd.). Wymagane jest pobranie skrótu zdarzeń (e1, e2, e3 itd.), Które są pogrupowane według daty następnie zadania i przeniesienia ich do zdarzeń pogrupowanych według , a następnie daty.Transpozycja hasza w ruby ​​z zamkiem

Eksperymentowałem z metodą #zip, ale to wymagałoby wstrzyknięcia zero w j1: d1, a następnie pozbycia się ich z wyników. Próbowałem również znaleźć przykład użycia #zip z argumentem blokowym. Rozumiem, że #zip with a block always returns nil, ale w rezultacie nie mogłem zrozumieć, w jaki sposób praktycznie go użyć.

require 'rspec' 
require 'pry' 

#  | d1 | d2 | d3 | 
#  ---------------------- 
# j1 |  | e2 | e3 | 
# -------------------------- 
# j2 | e4 | e5 | e6 | 
# -------------------------- 
# j3 | e7 |  | e9 | 
# -------------------------- 

def transpose(h) 
    Hash[ 
    dates(h).map do |d| 
     [ 
     d, 
     Hash[ h.keys.map do |j| 
      h[j][d] ? [j, h[j][d]] : nil 
     end.compact ] 
     ] 
    end 
    ] 
end 

def dates(h) 
    h.values.map(&:keys).reduce(:|).sort 
end 

describe "transpose" do 

    let(:starting) { 
    { 
     j1: { d2: :e2, d3: :e3 }, 
     j2: { d1: :e4, d2: :e5, d3: :e6 }, 
     j3: { d1: :e7, d3: :e9 } 
    } 
    } 

    let(:transposed) { 
    { 
     d1: { j2: :e4, j3: :e7 }, 
     d2: { j1: :e2, j2: :e5 }, 
     d3: { j1: :e3, j2: :e6, j3: :e9 } 
    } 
    } 

    it { expect(dates(starting)).to eq([:d1, :d2, :d3]) } 
    it { expect(transpose(starting)).to eq(transposed) } 
end 
+2

Chciałbym, aby każde pytanie tutaj było takie. Dobry przykład kodu z testami. – Yule

+0

Ciężko jest jednak podążać za twoim opisem - myślę, że używasz słowa 'hash' w miejscach, które miałeś na myśli' tablica', czy to prawda? ('hash of jobs',' hash of dates') - Przykład na końcu usuwa to. :) – BroiSatse

+0

Dzięki @Yule. Pisanie pytań jest sztuką samą w sobie! –

Odpowiedz

2

mam przepisany swój transpose metoda nieco powinno być szybsze i czystsze:

def transpose(h) 
    h.each_with_object({}) do |(outer, data), ret| 
     data.each do |inner, event| 
     ret[inner] = {} unless ret[inner] 
     ret[inner][outer] = event 
     end 
    end 
    end 

Nie używa zbędnych mapowanie dat i działa w obie strony (zmiany wewnętrzne i zewnętrzne klawiatura). Daj mi znać, co myślisz :)

+0

Piękne! Wielką zaletą pytania z testami jest to, że możesz skopiować i wkleić kod, aby sprawdzić, czy testy minęły :) Jest to znacznie czystsze niż moje rozwiązanie. Dzięki. ➜ SD GIT (PT98271602_scrollable_calendar) ✗ rspec ./stack_overflow_question.rb .. Wykończenie 0.00393 sekund dwa przykłady, 0 awarie –