# Creating a new array with sub-arrays of size given by the original one

Hello,

Trying to create an array with sub-arrays of size given by the elements of the original array like this:
[ [ 1 ], [ 2, 3 ], [ 4, 5, 6, 7 ], [ 8, 9, 10, 11, 12, 13, 14, 15 ] ]
from:
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
I came up with this:

``````(
a=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; x = []; c = Pseq(a,1).asStream;
i = 0;
while ( { (a.at(i)) > 0 }, { (j=a.at(i)); k = [c.nextN(j)]; x = x ++ k; a=a.shift((a.at(i)).neg);});
x.postln
)
``````

Which works, but in an example like this:

``````(
a = [ 3, 4, 2, 11, 8, 3, 1, 0, 7, 9, 6, 4, 4, 8, 1, 6, 5, 11, 8, 9 ]; x = []; c = Pseq(a,1).asStream;
i = 0;
while ( { (a.at(i)) > 0 }, { (j=a.at(i)); k = [c.nextN(j)]; x = x ++ k; a=a.shift((a.at(i)).neg);});
x.postln
)
``````

I get : [ [ 3, 4, 2 ], [ 11, 8, 3, 1, 0, 7, 9, 6, 4, 4, 8 ], [ 1 ], [ 6, 5, 11, 8, 9, nil ] ]

which is supposed to be due to the .shift method I’m using. So my questions are:

1. How could I chop off the “nil” results at the end?
2. Is there a better way to get the result I need?
3. and is there a way to get on the post window more elements instead of the “…etc…” when larger amounts of elements need to be displayed?

Thanks, I appreciate your help.
JF

1. How could I chop off the “nil” results at the end?

Perhaps:

``````+ Object {
nextNOrFewer {
arg anInteger;
var answer = List.new;
anInteger.do({
var next = this.next;
(next == nil).ifTrue({ ^answer });
answer.add(next);
});
^answer
}
}
``````
1. Is there a better way to get the result I need?

This seems fine, but also once you have a stream you don’t need the array as well?

I.e. you could, if you liked, write a groupByPrefixCount method simply in terms of next?

1. and is there a way to get on the post window more elements instead of the “…etc…” when larger amounts of elements need to be displayed?
``````(1 .. 200).asCompileString
``````

Ps. You can also delete nils afterwards, i.e.

``````+ SequenceableCollection {
takeUntilNil {
var endIndex = this.indexOf(nil);
(endIndex == nil).if({
^this
}, {
^this.copyRange(0, endIndex - 1)
})
}
}
``````

Thank you for such generous and accurate answers to all of my questions. The solution absolutely worked out. I appreciate that a lot. Regards, JF

Actually the method exists already:

``````a = [ [ 1 ], [ 2, 3 ], [ 4, 5, 6, 7 ], [ 8, 9, 10, 11, 12, 13, 14, 15 ] ];

b = (1..15).reshapeLike(a);
``````

The most likely is to ‘postcs’ the result (“post compile-string”) – but make sure you don’t have an infinitely recursive data structure (you probably don’t).

hjh

but I think OP wanted the size of each subarray to to be determined by its first element!

Hm, if you have a stream, then iterating over it should be enough…?

``````(
var num, j, item, subarray;
a = [ 3, 4, 2, 11, 8, 3, 1, 0, 7, 9, 6, 4, 4, 8, 1, 6, 5, 11, 8, 9 ];
x = [];
c = Pseq(a, 1).asStream;
num = c.next;  // that's right, not within the loop
while {
num.notNil and: { num > 0 }
} {
j = 0;
item = num;
subarray = [];
while {
item.notNil and: { j < num }
} {
subarray = subarray.add(item);
item = c.next;
j = j + 1;
};
x = x.add(subarray);
// moderate trickery:
// item is now the start of the next subarray!
// use this as num in the next cycle
num = item;
};
// unsure if you want to add a partial subarray here

// final result
x
)
``````

Haven’t tested but this should be pretty close. Edited because the subarray handling wasn’t right the first time.

Ah, my misreading. Hope the stream-iteration approach is helpful.

hjh

Here’s another version, which avoids the nested loop:

``````(
var remain, item, subarray;
a = [ 3, 4, 2, 11, 8, 3, 1, 0, 7, 9, 6, 4, 4, 8, 1, 6, 5, 11, 8, 9 ];
x = [];
c = Pseq(a, 1).asStream;
subarray = [];
remain = 0;
while {
item = c.next;
item.notNil
} {
if(remain > 0) {
subarray = subarray.add(item);
remain = remain - 1;
} {
if(subarray.size > 0) {
x = x.add(subarray);
};
subarray = [item];
remain = item - 1;  // because we already took one
};
};
// subarray is always initialized to at least one item
// therefore there is always something left to add here
x = x.add(subarray);

// final result
x
)
``````

hjh

Thank you, James, for both insightful solutions, I appreciate them, regards, JF.