2016-11-13 13 views
5

Powiedzmy mam tablicę długościach czas wyrażony w minutach:Dowolna standardowa metoda podobna do dotknięcia, ale zwrócenie wyniku bloku zamiast własnego?

minutes = [20, 30, 80] 

chciałbym podsumować zawartość tablicy i wyjście wynik w formacie <hours>:<minutes>. Dla powyższego przykładu oczekuję, że wynik będzie 02:10.

Czy istnieje standardowa metoda Ruby (tj. Zawarta w core lub std-lib) umożliwiająca wykonanie tej operacji w łańcuchu metod o jednej linii? (tj. bez użycia zmiennej do przechowywania wyniku pośredniego). Mam na myśli coś takiego:

puts minutes.reduce(:+).foomethod { |e| sprintf('%02d:%02d', e/60, e % 60) } 

Co foomethod być? Object.tap jest dość zbliżony do tego, czego potrzebuję, ale niestety zwraca self zamiast wyniku bloku.

+2

patrz http://stackoverflow.com/a/7879071/2981429 dla łatwego sposobu zdefiniowania takiej metody; możesz również uczynić element tablicą jednoelementową i użyć 'map'. –

+1

To odpowiada na moje pytanie: nie ma metody robienia tego w standardowej Ruby, musisz zdefiniować własną. –

+0

BTW smutny. Za pomocą innej metody klasy obiektu, podobnej do dotknięcia, bue zwraca wynik, wiele kodów będzie czystszych, a wiele łańcuchów może być dłuższych bez pośredniej zmiennej czasowej. – jgomo3

Odpowiedz

3

Spróbuj jeden

puts sprintf('%02d:%02d', *minutes.reduce(:+).divmod(60)) 
+0

Ładne rozwiązanie konkretnego przykładu! Nie pamiętam metody "divmod", dzięki! W każdym razie nie odpowiada na moje pierwsze pytanie "Jakąkolwiek standardową metodę podobną do dotknięcia, ale zwraca wynik bloku zamiast własnego?". Myślę, że odpowiedź brzmi "nie". –

+0

Tak, myślę, że musisz zdefiniować jedno na własną rękę :) – Ursus

3
proc { |e| sprintf('%02d:%02d', e/60, e % 60) }.call(minutes.reduce(:+)) #=>"01:00" 

lub jeśli wolisz lambdy

->(e) { sprintf('%02d:%02d', e/60, e % 60) }.call(minutes.reduce(:+)) #=>"01:00" 

PS: Jeśli chcesz zrobić to jeszcze krócej, można również użyć [] i .() do wywoływania lambda, tj.

->(e) { sprintf('%02d:%02d', e/60, e % 60) }.(minutes.reduce(:+)) #=>"01:00" 
->(e) { sprintf('%02d:%02d', e/60, e % 60) }[minutes.reduce(:+)] #=>"01:00" 
+1

Ładne rozwiązanie! Pomaga mi uzyskać odpowiedź na moje pierwsze pytanie "Jakąkolwiek standardową metodę podobną do dotknięcia, ale zwraca wynik bloku zamiast własnego?": Myślę, że odpowiedź brzmi "nie". BTW, nawet jeśli jest to jeden liniowiec, nie jest tak "liniowy", jak bym chciał: wyobraź sobie, gdybyś miał znacznie dłuższy łańcuch metod! W rzeczywistości był to tylko przykład. Więc gdybym musiał wybrać, osobiście wybrałbym klarowność, używając zmiennej do przechowywania wyniku pośredniego. –