I’m trying to split an incoming list of numbers to fill an ArrayList. Each new chopped IntList would have a different size, and on the incoming -unchopped- list i can use -1 as the separator.
I’m having problems to parse correctly the incoming list and distribute the slices in the ArrayList, as it looks like with my terrible code just the last slice is filling the whole ArrayList. I’ve been trying to achieve the result i’d expect for hours, but i can’t find the solution for myself…
Is anyone familiar with this kind of “list-chopping” operations and can give me a hand?
(The code i’m attaching is a stripped-down version… on my final application the list to be chopped will be received through OSC… and that would explain why the first number in the list is the length of the list. As far as i know there’s no way to retrieve the size of an OSC message, so i managed to add the size on the first position on my OSC sending Max/MSP patch)
ArrayList <IntList> Scales = new ArrayList <IntList>();
IntList oscList=new IntList(16,-1,0,1,2,3,-1,10,20,30,40,-1,100,200,300,400,500);
int oscListSize;
void setup(){
}
void draw(){
}
void keyPressed() {
Scales.clear();
IntList tmp=new IntList(); //temporary list
int counter=0;
oscListSize = oscList.get(0); //the first value of oscList is the size of the list itself
for(int i=1;i<oscListSize+1;i++){
int num=oscList.get(i);
if(num==-1){ //-1 is the "separator" between lists
Scales.add(tmp); //add the tmp intlist to the Scales arraylist
tmp.clear(); //afterwards, clear tmp
counter=counter+1;
}
else{
tmp.append(num); //if num is different to -1, add it to the tmp list
}
}
println(Scales); //print the result (which is not the expected one)
}
For loop over it first (sorry, this was not the reason)
SOLVED —
your program was correct, but you need to make a copy here: Scales.add(tmp.copy());
to get a new object or whatever
(also I appended -1 as mentioned)
and you can use size() here: for (int i=0; i<oscList.size();
Chrisir
// source
IntList oscList=new IntList(16, -1, 0, 1, 2, 3, -1, 10, 20, 30, 40, -1, 100, 200, 300, 400, 500, -1);
//destiny
ArrayList <IntList> Scales = new ArrayList <IntList>(); ....
void setup() {
size(330, 330);
}
void draw() {
//
}
// ------------------------------------------------------------------------------
void keyPressed() {
//
Scales.clear();
IntList tmp=new IntList(); //temporary list
int counter=0;
for (int i=0; i<oscList.size(); i++) {
int num=oscList.get(i);
if (num==-1) { //-1 is the "separator" between lists
Scales.add(tmp.copy()); //add the tmp intlist to the Scales arraylist // COPY
tmp.clear(); //afterwards, clear tmp
counter=counter+1;
} else {
tmp.append(num); //if num is different to -1, add it to the tmp list
}
}
println(Scales); //print the result (which is not the expected one)
println("---");
for (IntList intl : Scales) {
println(intl);
}
}
//
This sketch will split an IntList into multiple lists on a given value. It ignores the first element in the list because this is not a value but rather the number of elements in the ocs message. The algorithm is ‘stable’ in that it does not alter the order of the elements within the original list.
You should be able to adapt this to suit your own sketch.
IntList oscList = new IntList(16, -1, 0, 1, 2, 3, -1, 10, 20, 30, 40, -1, 100, 200, 300, 400, 500);
ArrayList<IntList> scales;
void setup() {
size(600, 400);
scales = splitter(oscList, -1);
for (IntList i : scales)
println(i);
}
ArrayList<IntList> splitter(IntList list, int splitOn) {
ArrayList<IntList> lists = new ArrayList<IntList>();
IntList temp = new IntList();
// ignore element containing list size
for (int idx = 1, len = list.size(); idx < len; idx++) {
int element = list.get(idx);
if (element == splitOn) {
if (temp.size() > 0) {
lists.add(temp);
temp = new IntList();
}
} else {
temp.append(element);
}
}
// Add any list left over
if (temp.size() > 0)
lists.add(temp);
return lists;
}
Wow! thanks for your unvaluable help @Chrisir and @quark!
Both solutions do the job, and now i can go on developing my sketch… yeehaa!!!
This is going to be part of an spectrogram generator which i’ve been working with for a couple of years, and which create images that “sound good” when IFFT’d:
With this help of yours, now i will be able to define a different chord per bar, which was something lacking until now!
Thank you very much!
Please drop a line if you ever come around Barcelona and i’ll be glad to invite you to some beers!!!
Well, I did a 3rd solution using IntList’s method getSubset(); plus its methods removeValue() & copy():
/**
* Split IntList by a Separator Value (v1.0.0)
* GoToLoop (2022/Aug/24)
*
* https://Discourse.Processing.org/t/
* splitting-a-list-of-ints-using-a-special-number-as-a-separator/38471/9
*/
static final IntList OSC_VALS = new IntList(
16, -1, // list size
0, 1, 2, 3, -1,
10, 20, 30, 40, -1,
100, 200, 300, 400, 500
);
static final int SEPARATOR = -1;
import java.util.Collection;
Collection<IntList> scales;
void setup() {
// Skipping 1st & 2nd elements containing list size and its separator:
final IntList oscVals = OSC_VALS.getSubset(2);
scales = splitter(oscVals, SEPARATOR);
for (final IntList list : scales) println(list);
exit();
}
static final Collection<IntList> splitter(final IntList list, final int sep) {
// Result collection of split subsets from recieved IntList:
final Collection<IntList> splits = new ArrayList<IntList>();
// Cloning received IntList so we're free to use removeValue() on it:
final IntList clone = list.copy();
// Iterator prevIdx is previous index where separator value was found:
for (int idx, prevIdx = 0; prevIdx >= 0; prevIdx = idx) {
// Remove & get index of 1st found separator value. Otherwise gets -1:
idx = clone.removeValue(sep);
// Add() a new IntList subset to splits starting from index prevIdx:
if (idx >= 0) splits.add(clone.getSubset(prevIdx, idx - prevIdx));
else splits.add(clone.getSubset(prevIdx)); // no separator found
}
return splits;
}
I never imagined there could be so many ways to face this problem… i’m ashamed of how much knowledge i still need to glimpse…
Certainly, the getSubset() method of IntList is a powerful tool.
I’m sure i’m going to use it a lot on the forthcoming weeks… i have many lists to process!!!
Again, i’d be pleased to thank you for your help if you ever come around Catalonia… please drop a line and we’ll be happy to host you at our beautiful place at Playmodes headquarters!