Reputation: 5749
If data at the end of a list are more important, and I want :partial list to be left at the beginning of the list while preserving the initial order, I do this:
> my @a = (0,1,2,3,4,5,6,7,8,9);
[0 1 2 3 4 5 6 7 8 9]
> say @a.rotor(4, :partial)
((0 1 2 3) (4 5 6 7) (8 9)) # not what I want; important data at end gets cut off;
> say @a.reverse.rotor(4, :partial).reverse.map({$_.reverse});
((0 1) (2 3 4 5) (6 7 8 9)) # this is what I want
Is there a way to avoid the 3 "reverse" operations? Is it possible to add a :fromEnd adverb?
Upvotes: 6
Views: 253
Reputation: 34120
You could calculate the number of elements left in the :partial
list.
@a.elems % 4
Then combine it with a repeating sequence of the size you wanted.
4 xx *
If you tried to combine them simply it won't work
@a.elems % 4, 4 xx *
That is because the above is a list of two elements. The first is the result of the modulus operation, and the second is an infinite sequence.
You can just use flat
to make them a single sequence.
flat @a.elems % 4, 4 xx *
Here is the resulting code.
@a.rotor( flat @a.elems % 4, 4 xx * )
Upvotes: 1
Reputation: 4465
You can use @a.rotor(2,4,4)
or a little more universal @a.rotor(@a
% 4,slip 4 xx *)
. Of course, you could define function
multi batch ( $_, $n, :from-end($)! ) {
.rotor: .elems % $n, slip $n xx *
}
say batch ^10, 4,:from-end; #or even
say (^10).&batch(4):from-end;
Upvotes: 6
Reputation: 5058
my @a = (0,1,2,3,4,5,6,7,8,9);
my @b = @a.rotor(4, :partial)».elems.reverse;
say @a.rotor(|@b);
Upvotes: 6
Reputation: 26924
Taking the last question first: Yes, it is possible, but it would probably be called :end
for consistency, and no I don't think it is likely to be added. But then I could be wrong :-)
I'm not sure how golfed your example is, but if you're really working from an array, why not stuff it first with values to make it evenly divisible by 4, and then remove them afterwards again:
my @a = ^10;
@a.splice(0,0, Any xx @a % 4);
say @a.batch(4); # (((Any) (Any) 0 1) (2 3 4 5) (6 7 8 9))
Note I've used the shorter ^10
(which is a range from 0
to 10
, excluding the endpoint). And I've used the simpler batch
method, as we are sure there won't be any partial lists. In any case, no reverse
is needed, just checking values afterwards.
Mind you, the reverse
method on an array, is relatively cheap, as it does not actually move any values.
Upvotes: 3