2016-07-16 31 views
0

Hier ist, was ich bin in diesem Augenblick, dass derzeit Arbeiten zu tun, aber ich fühle mich ein bisschen in syntaktischer Zucker fehlt ...Können Blockparameter eines Array-Elements, das in einen Block für die inject-Methode übergeben wird, separat deklariert werden?

f = RGeo::Geos.factory 
coords = [ [1,1], [2,2], [1,3] ] 
points = coords.inject([]) {|points, coord| points << f.point(coord[0], coord[1]); points } 
#=> [#<RGeo::Geos::CAPIPointImpl:0x3fff0950a508 "POINT (1.0 1.0)">, #<RGeo::Geos::CAPIPointImpl:0x3fff0950a47c "POINT (2.0 2.0)">, #<RGeo::Geos::CAPIPointImpl:0x3fff0950a454 "POINT (1.0 3.0)">] 

Hier ist, was ich tun möchte:

points = coords.inject([]) {|points, x, y| points << f.point(x,y); points } 
#=> [nil, nil, nil] 

Im Moment gibt das ein Array von drei Nullwerten zurück. Ist es möglich, die Array-Werte eines Elements, das in den inject-Block übergeben wird, getrennt zu deklarieren, so wie es mit jeder Methode möglich ist?

Seitennotiz: Es ist sicher, denselben Variablennamen für den ersten inject-Block-Parameter (die Variable "result") und die Variable auf der linken Seite des Gleichheitszeichens zu verwenden, richtig? Ich denke ja, denn das wäre nur ein typischer Fall von Rekursion. Bitte kommentiere, wenn du etwas anderes fühlst oder weißt.

+0

warum 'inject', es sieht aus wie 'map' würde tun? –

+0

Ich nehme an, du hast Recht. Ich überlegte es mit Sicherheit. –

Antwort

1

Dies wird den Trick:

points = coords.inject([]) {|points, (x, y)| points << f.point(x,y); points } 

Diese Regel in jedem Block arbeitet; Wenn einer der Blockparameter ein Array von n Elementen ist, können Sie diese Elemente mit n Parentnamen in Klammern erfassen. Wenn Sie mehr als n Parameternamen in Klammern verwenden, werden die Extras nil:

[[1,2,3],[4,5]].map {|(a,b,c)| "#{a}+#{b}+#{c.inspect}" } #=> ["1+2+3", "4+5+nil"] 

Wenn Sie zu wenig verwenden, Parameternamen, wird der Rest verworfen werden:

[[1,2,3],[4,5]].map {|(a,b)| "#{a}+#{b}" } #=> ["1+2", "4+5"] 

Sie die verwenden können, splat-Operator zu erfassen, um den Rest stattdessen genau wie bei regulären Argumenten:

[[1,2,3],[4,5]].map {|(a,*b)| "#{a}+#{b}" } #=> ["1+[2, 3]", "4+[5]"] 

Sie können sogar Nest:

[[1,2,[3,4]],[5,6,[7,8]]].map {|(a,b,(c,d))| a+b+c+d } #=> [10, 26] 

Denken Sie daran, dass das Verschachteln ziemlich schnell verwirrend sein kann, also verwenden Sie es sparsam.

Beachten Sie auch, dass diejenigen, äußere Klammer sind nicht streng, notwendig in den obigen Beispielen, aber sie verändern das Verhalten, wenn nur ein Argument aus dem Array genommen wird:

# Makes no difference 
[[1,2,3],[4,5,6]].map {| a,b,c | "#{a}+#{b}+#{c}" } #=> ["1+2+3", "4+5+6"] 
[[1,2,3],[4,5,6]].map {|(a,b,c)| "#{a}+#{b}+#{c}" } #=> ["1+2+3", "4+5+6"] 

# Makes a big difference 
[[1,2,3],[4,5,6]].map {| a | a } #=> [[1, 2, 3], [4, 5, 6]] 
[[1,2,3],[4,5,6]].map {|(a)| a } #=> [1, 4] 
+0

Wow! Ich liebe es, wie ich auch nach 4 Jahren Arbeit immer noch mehr über die syntaktischen Fähigkeiten von Ruby lerne –