#FEATURE by exept
class: SequenceableCollection
added: #inGroupsOf:detect:thenDo:ifNone:
--- a/SequenceableCollection.st Mon Sep 09 16:15:21 2019 +0200
+++ b/SequenceableCollection.st Mon Sep 09 18:06:34 2019 +0200
@@ -1,5 +1,3 @@
-"{ Encoding: utf8 }"
-
"
COPYRIGHT (c) 1989 by Claus Gittinger
All Rights Reserved
@@ -5384,6 +5382,68 @@
"Modified: / 27-10-2006 / 10:07:02 / cg"
!
+inGroupsOf:n detect:anNArgBlock thenDo:anotherNArgBlock ifNone:exceptionValue
+ "evaluate the argument, anNArgBlock for every group of n elements in the collection,
+ until the block returns true. Then deliver the to anotherNArgBlock and return
+ that block's result. If none matches, return the valeu from exceptionValue.
+ An error will be reported, if the number of elements in the receiver
+ is not a multiple of n.
+ This is similar to slicesOf:detect:, but here, an N-arg block is expected."
+
+ |stop argVector|
+
+ stop := self size.
+
+ "/ the reason for inlining the cases for 2/3 args is to avoid the temporary object creation, and to
+ "/ allow for the compiler (jitter) to generate better code for the block-call
+ n == 2 ifTrue:[
+ 1 to:stop by:2 do:[:index |
+ |a1 a2|
+
+ a1 := self at:index.
+ a2 := self at:index+1.
+ (anNArgBlock value:a1 value:a2) ifTrue:[
+ ^ anotherNArgBlock value:a1 value:a2
+ ].
+ ].
+ ^ exceptionValue value.
+ ].
+ n == 3 ifTrue:[
+ 1 to:stop by:3 do:[:index |
+ |a1 a2 a3|
+
+ a1 := self at:index.
+ a2 := self at:index+1.
+ a3 := self at:index+2.
+ (anNArgBlock value:a1 value:a2 value:a3) ifTrue:[
+ ^ anotherNArgBlock value:a1 value:a2 value:a3
+ ].
+ ].
+ ^ exceptionValue value.
+ ].
+
+ argVector := Array new:n.
+ 1 to:stop by:n do:[:index |
+ argVector replaceFrom:1 to:n with:self startingAt:index.
+ (anNArgBlock valueWithArguments:argVector) ifTrue:[
+ ^ anotherNArgBlock valueWithArguments:argVector
+ ].
+ ].
+ ^ exceptionValue value.
+
+ "
+ #(1 one 2 two 3 three 4 four 5 five 6 six)
+ inGroupsOf:2 detect:[:num :sym | num > 3]
+ thenDo:[:num :sym | sym] ifNone:'ouch'
+
+ #(1 one 2 two 3 three 4 four 5 five 6 six)
+ inGroupsOf:2 detect:[:num :sym | num > 99]
+ thenDo:[:num :sym | sym] ifNone:'ouch'
+ "
+
+ "Modified: / 27-10-2006 / 10:07:02 / cg"
+!
+
inGroupsOf:n do:anNArgBlock
"evaluate the argument, anNArgBlock for every group of n elements in the collection.
The block is called with n arguments for group of n consecutive elements in the receiver.