Put Arrays in Dictionary consecutively

Hey, i have three arrays as the result of some functions (two nested ones) and would like to put them into a dictionary consecutively and order them by size. But im always rewriting with ~high_abs. The result should be 0-> [8], 1 → [3,5], 2 → [3,3,2], 3 → [3,1,2,2], 4 → [ 2,1,1,2,2 ], 5 → [ 2,1,1,1,1,2 ], 6 → [1,1,1,1,1,1,2], 7 → [1,1,1,1,1,1,1,1]

simplified code here:

(
//create Dictionary for abstractions
~absDict = Dictionary.new;

~lsys = #[3,1,2,2];

//add L-System
~absDict.put(0, ~lsys);

//add abstractions with lower density to the dictionary
~low_abs = [[ 3, 3, 2 ], [ 3, 5 ], [ 8 ]];
~low_abs.do({
	arg el, elindex;
	~absDict.put((elindex+1), el);
});

//add abstractions with higher density to the dictionary
~high_abs = [[ 2, 1, 1, 2, 2 ], [ 2, 1, 1, 1, 1, 2 ], [ 1, 1, 1, 1, 1, 1, 2 ], [ 1, 1, 1, 1, 1, 1, 1, 1 ]];

~high_abs.do({
	arg el, elindex;
	~absDict.put((elindex+1), el);
});

//get Dictionary in Order array.size low -> high
~absDict = ~absDict.atAll(~absDict.order.reverse);

~absDict.debug("abs dict");
)

I don’t quite understand what your code is doing. Is ~low_abs and ~high_abs being generated by a function? Could you share what kind of arguments it takes?

You generally should avoid using .put and prefer to recreate the collection from scratch for each operator you apply to it. You could try using .collect to apply a function to each element of a collection and returning a new collection of same size, or .inject to sequentially apply a function to a collection using an accumulator returning a single value.

UPDATE have updated ~high_abs should work now…

(
~lsys = #[3,1,2,2];
//functions for building Abstractions
//creating abstractions with lesser density: reduce the density by joining two values

~low_dens = {
	arg array;
	var ioi, result = [], min_index, neighbor_index;
	ioi = array.copy();

	ioi.debug("start ioi");

	while {ioi.size() > 1} {
		// in every step, we will reduce ioi until it has size 1
		var intermediate_result = [];
		min_index = ioi.minIndex;

		// if first element is minimum element, the neighor can only be to the right
		if (min_index == 0) {
			neighbor_index = 1;
		} {
			// else if last element is minimum element, the neighbor can only be to the left
			if (min_index == (ioi.size - 1)) {
				neighbor_index = (ioi.size - 2);
			} {
				// else we're in the middle, so use the neighbor which is smallest (arbitrary choice)
				var dir = 1;
				if (ioi[min_index - 1] < ioi[min_index + 1]) {
					dir = -1;
				};
				neighbor_index = min_index + dir;
			};
		};
		// swap neighbor and min_index so that neighbor is always bigger than min_index
		// - this makes copying easier in the next step
		if (neighbor_index < min_index) {
			var tmp = min_index;
			min_index = neighbor_index;
			neighbor_index = tmp;
		};

		// make a new list consisting of everything before min_index, sum of min el and its neighbor, everything after neighbor
		intermediate_result = ioi.copyRange(0, min_index-1) ++ (ioi[min_index] + ioi[neighbor_index]) ++ ioi.copyRange(neighbor_index+1, (ioi.size-1));

		if (intermediate_result.size >= ioi.size) {
			"ERROR!".postln;
		};

		// add it to the list of results
		result = result.add(intermediate_result);

		// and update our starting point with the reduced list
		ioi = intermediate_result.copy();
	};

	// return the complete list of reductions
	result;
};

/*
creating abstractions with higher density by replacing a value with:
1. a smaller potential IOI value
2. and the difference between it and the value being replaced
*/

~high_dens = {
	arg array;
	var ioi, ioi_sort, pot_ioi, result = [], index_max;
	ioi = array.copy();
	ioi.debug("start ioi");

	ioi_sort = ioi.as(Set).as(Array).sort;
	pot_ioi = ioi_sort.minItem;

	while { ioi.maxItem > pot_ioi } {
		var intermediate_result = [];

		index_max = ioi.findAll([ioi.maxItem]).choose;

		intermediate_result = intermediate_result.add(ioi).debug;
		intermediate_result = intermediate_result.insert(index_max+1, [ioi[index_max] - pot_ioi, pot_ioi]).flat;
		intermediate_result.removeAt(index_max);

		// add it to the list of results
		result = result.add(intermediate_result);

		// and update our starting point with the reduced list
		ioi = intermediate_result.copy();

	};

	result;
};

//create Dictionary for abstractions
~absDict = Dictionary.new;

//add L-System to the dictionary
~absDict.put(0, ~lsys);

//add abstractions with lower density to the dictionary
~low_abs = ~low_dens.(~lsys);
~low_abs.do({
	arg el, elindex;
	~absDict.put((elindex+1), el);
});

//add abstractions with higher density to the dictionary
~high_abs = ~high_dens.(~lsys);
~high_abs.do({
	arg el, elindex;
	~absDict.put((elindex), el);
});

//get Dictionary in Order array.size low -> high
~absDict = ~absDict.atAll(~absDict.order.reverse);

~absDict.debug("abs dict");
)

If you want the dictionary key to be the array size, then… elIndex is not the size.

el.size is the size.

So the high_abs loop is putting the first 6-element array in at dictionary key 0.

Should have written ~absDict.put(el.size, el).

Next question – do you ever need to save more than one array with the same size? If yes, then it would be ~absDict.put(el.size, ~absDict.at(el.size).add(el)) or the equivalent ~absDict[el.size] = ~absDict[el.size].add(el) – then you’d have an array of all previously stored arrays. (put overwrites, so your original way could preserve only the latest of each size – which may be what you want, or not, that’s up to you.)

hjh

thanks so much its working now :slight_smile:

 (
    // first we define some functions
    ~rewriteWord = {
    	arg word, rules, iter=6;
        iter.do{
    		word = Array.newFrom(word)
    		.collect{|c| rules[c.asSymbol]}
    		.join;
        };
        word
    };

    ~getDur =  {
    	arg word, notesDict;
      // streams are created inside this function
      // so every time we call ~getDur, streams are resetted
      var streams = notesDict.collect{
    		arg seq;
    		Pseq(seq,inf).asStream};
      Array.newFrom(word).collect{|c| streams[c.asSymbol].next }
    };

    // now define rules
    r = (A:"AB", B:"A");

    // define durations for each symbol
    ~lsys = (

    	A: [0.25, 0.5, 0.25],
    	B: [0.5, 0.5, 0.25],

    );

    // Axiom
    w = "A";
    // rewriting iteration
    w = ~rewriteWord.(w,r,6);
    // getting durations
    d = ~getDur.(w,~lsys);

    //function for cropping L-System
    ~sumUpTo = {
    	arg array, total;
    	var sum = 0, i = 0, result = Array.new;
    	while { i < array.size and: { sum < total } } {
    		sum = sum + array[i];
    		if(sum > total) {
    			result = result.add(array[i] - (sum - total));
    		} {
    			result = result.add(array[i]);
    		};
    		i = i + 1;
    	};
    	result
    };

    //crop L-System to specific length
    ~lsys = ~sumUpTo.(d, 4);

    //~lsys = #[3,1,2,2];
    //functions for building Abstractions
    //creating abstractions with lesser density: reduce the density by joining two values

    ~low_dens = {
    	arg array;
    	var ioi, result = [], min_index, neighbor_index;
    	ioi = array.copy();

    	ioi.debug("start ioi");

    	while {ioi.size() > 1} {
    		// in every step, we will reduce ioi until it has size 1
    		var intermediate_result = [];
    		min_index = ioi.minIndex;

    		// if first element is minimum element, the neighor can only be to the right
    		if (min_index == 0) {
    			neighbor_index = 1;
    		} {
    			// else if last element is minimum element, the neighbor can only be to the left
    			if (min_index == (ioi.size - 1)) {
    				neighbor_index = (ioi.size - 2);
    			} {
    				// else we're in the middle, so use the neighbor which is smallest (arbitrary choice)
    				var dir = 1;
    				if (ioi[min_index - 1] < ioi[min_index + 1]) {
    					dir = -1;
    				};
    				neighbor_index = min_index + dir;
    			};
    		};
    		// swap neighbor and min_index so that neighbor is always bigger than min_index
    		// - this makes copying easier in the next step
    		if (neighbor_index < min_index) {
    			var tmp = min_index;
    			min_index = neighbor_index;
    			neighbor_index = tmp;
    		};

    		// make a new list consisting of everything before min_index, sum of min el and its neighbor, everything after neighbor
    		intermediate_result = ioi.copyRange(0, min_index-1) ++ (ioi[min_index] + ioi[neighbor_index]) ++ ioi.copyRange(neighbor_index+1, (ioi.size-1));

    		if (intermediate_result.size >= ioi.size) {
    			"ERROR!".postln;
    		};

    		// add it to the list of results
    		result = result.add(intermediate_result);

    		// and update our starting point with the reduced list
    		ioi = intermediate_result.copy();
    	};

    	// return the complete list of reductions
    	result;
    };

    /*
    creating abstractions with higher density by replacing a value with:
    1. a smaller potential IOI value
    2. and the difference between it and the value being replaced
    */

    ~high_dens = {
    	arg array;
    	var ioi, ioi_sort, pot_ioi, result = [], index_max;
    	ioi = array.copy();
    	ioi.debug("start ioi");

    	ioi_sort = ioi.as(Set).as(Array).sort;
    	pot_ioi = ioi_sort.minItem;

    	while { ioi.maxItem > pot_ioi } {
    		var intermediate_result = [];

    		index_max = ioi.findAll([ioi.maxItem]).choose;

    		intermediate_result = intermediate_result.add(ioi).debug;
    		intermediate_result = intermediate_result.insert(index_max+1, [ioi[index_max] - pot_ioi, pot_ioi]).flat;
    		intermediate_result.removeAt(index_max);

    		// add it to the list of results
    		result = result.add(intermediate_result);

    		// and update our starting point with the reduced list
    		ioi = intermediate_result.copy();

    	};

    	result;
    };

    //create Dictionary for abstractions
    ~absDict = Dictionary.new;

    //add abstractions with lower density to the dictionary
    ~low_abs = ~low_dens.(~lsys);
    ~low_abs.do({
    	arg el, elindex;
    	~absDict.put((el.size), el);
    });

    //add L-System after abstractions with lower density to Dictionary
    ~absDict.put(~absDict.size+1, ~lsys);

    //add abstractions with higher density to the dictionary
    ~high_abs = ~high_dens.(~lsys);
    ~high_abs.do({
    	arg el, elindex;
    	~absDict.put((el.size), el);
    });

    //get Dictionary in Order array.size low -> high
    ~absDict = ~absDict.atAll(~absDict.order);

    ~absDict.debug("abs dict");
    )

    (
    Pdef(\kick,
    	Pbind(
    	\instrument, \kick,
    	\buf, ~samples[\kick][14],

    	\dur, Pn(Plazy {Pseq(~absDict.at(10), 1)},inf).trace,

    	\legato, Pfunc({rrand(0.01,1.0)}),
    	\atk, 0.01,

    	\gainEnv, Pfunc{|e|
    			var rel = (1 - e.atk);
    			Env.perc(e.atk, rel);
    		},

    	\ffreq, 110,
    	\drivegain, 0.2,

    	\amp, 0.5,
    	\pan, Pwhite(-0.25,0.25, inf),
    	)
    ).play(t, quant:1);
    )

    Pdef(\kick).stop;