2015-11-17 13 views
5

Znalazłem kodu przez użytkownika Hirolau:bloku z dwoma parametrami

def sum_to_n?(a, n) 
    a.combination(2).find{|x, y| x + y == n} 
end 

a = [1, 2, 3, 4, 5] 
sum_to_n?(a, 9) # => [4, 5] 
sum_to_n?(a, 11) # => nil 

Skąd mogę wiedzieć, kiedy mogę wysłać dwa parametry do predefiniowanej metody jak find? Nie jest dla mnie jasne, ponieważ czasami to nie działa. Czy to jest coś, co zostało na nowo zdefiniowane?

+0

Zobacz tę odpowiedź - http://stackoverflow.com/a/1077751/196834 – Ash

+0

Żeby było jasne, znaleźć trwa 1 opcjonalny argument i blok. Blok przyjmuje dwa argumenty. –

+0

Jestem hirolau i aprobuję tę wiadomość. – hirolau

Odpowiedz

6

Jeśli spojrzysz na dokumentację Enumerable#find, zobaczysz, że akceptuje tylko jeden parametr do bloku. Powodem, dla którego można wysłać dwa, dlatego Ruby wygodnie pozwala to zrobić z bloków, na podstawie To „przypisanie równoległy” strukturze:

[[1,2,3], [4,5,6]].each {|x,y,z| puts "#{x}#{y}#{z}"} 
# 123 
# 456 

Więc w zasadzie, każdy plony element tablicy do bloku, a ponieważ Składnia bloków ruby ​​umożliwia "rozszerzanie" elementów tablicy na ich składniki poprzez dostarczanie listy argumentów, działa.

Możesz znaleźć więcej lew z argumentami bloków here.

a.combination(2) daje tablicę tablic, gdzie każda z podelementów składa się z 2 elementów. Więc:

a = [1,2,3,4] 
a.combination(2) 
# => [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]] 

W rezultacie, wysyłasz jedną tablicę jak [1,2] znaleźć na blok, a Ruby wykonuje zadania równolegle do przypisania 1 do x i 2 do y.

patrz także this SO pytanie, które przynosi inne wydajne przykłady przypisania równolegle, jak to stwierdzenie:

a,(b,(c,d)) = [1,[2,[3,4]]] 
+0

A następnie, jak mogę nauczyć się rzeczy takich jak "przypisanie równoległe", "dekompozycja" i jak Ruby "Składnia bloków pozwala na rozszerzanie elementów tablicy" Mam na myśli, przeczytałem kilka książek i tutoriali on line i nigdy nie czytałem tego, czy możesz mi dać wskazówka, aby zacząć szukać proszę? Dzięki za odpowiedź BTW. –

+0

Nie mam dla Ciebie dobrego zasobu. Najlepszą książką jaką czytałem o Rubim jest "Metaprograming Ruby" Paolo Perrotta (wydana przez The Pragmatic Programmers), ale właśnie sprawdziłem - nie wspomina o nich. Jest to użyteczny przypadek krawędzi równoległego przypisania wyjaśniony w większości samouczków (np. Http://www.tutorialspoint.com/ruby/ruby_operators.htm). W języku są rzeczy, których nawet doświadczeni programiści uczą się, a im więcej kodu czytasz, tym więcej sztuczek zdobędziesz w rękawie. Zdecydowanie polecam tę książkę. Łatwe do odczytania i dostaniesz z tego dużo. – AmitA

0

W find funkcyjne iteracje nad elementami, trwa jeden argument, w tym przypadku blok (który bierze dwa argumenty za hash):

h = {foo: 5, bar: 6} 
result = h.find {|k, v| k == :foo && v == 5} 
puts result.inspect #=> [:foo, 5] 

Blok zajmuje tylko jeden argument dla tablic choć chyba używasz destrukturyzacji.

Aktualizacja: Wygląda na to, że w tym przypadku następuje destrukcja.

+0

W przypadku skrótu, 'to_a' jest niejawnie stosowane, więc jest takie samo jak w tablicy. – sawa

+0

Tak. Muszę przyznać, że metoda "combination" zwróciła hasz i chciała dać prostą odpowiedź bez wchodzenia w destrukturyzację i takie tam, ale nie trafiłem w sedno. –

3

find nie mają dwa parametry, to przyjmuje jedną. Powodem, dla którego blok w twoim przykładzie przyjmuje dwa parametry, jest to, że używa destrukcji. Poprzedni kod a.combination(2) daje tablicę tablic złożonych z dwóch elementów, a nad nią iteruje find. Każdy element (tablica dwóch elementów) jest przekazywany jednocześnie do bloku jako jego pojedynczy parametr. Jednak podczas pisania więcej parametrów niż jest, Ruby próbuje dostosować parametry poprzez niszczenie tablicy. Część:

find{|x, y| x + y == n} 

jest skrótem do zapisu:

find{|(x, y)| x + y == n} 
+1

Uważam, że to "destrukturyzacja", a nie rozkład. +1 za podanie alternatywy paren. –