2 *newFrom { | aCollection |
3 var newCollection = this.new(aCollection.size);
4 aCollection.do {| item | newCollection.add(item) };
9 // answer a collection of my class of the given arguments
10 // the class Array has a simpler implementation
11 newColl = this.new(args.size);
15 *fill { | size, function |
19 obj.add(function.value(i));
24 @ { | index | ^this[index] }
27 if (aCollection.class != this.class) { ^false };
28 if (this.size != aCollection.size) { ^false };
30 // this is enough since both collections are finite
31 if ((aCollection.includes(item)).not) { ^false };
36 var hash = this.class.hash;
38 hash = hash bitXor: item.hash;
44 do { ^this.subclassResponsibility(thisMethod) }
46 ^r { this.do {|item| item.yield } }
49 // this is the slow way. Most collections have a faster way.
51 this.do { tally = tally + 1 };
58 isEmpty { ^this.size == 0 }
59 notEmpty { ^this.size > 0 }
60 asCollection { ^this }
62 add { ^this.subclassResponsibility(thisMethod) }
63 addAll { | aCollection | aCollection.asCollection.do { | item | this.add(item) } }
64 remove { ^this.subclassResponsibility(thisMethod) }
65 removeAll { | list | list.do { | item | this.remove(item) } }
66 removeEvery { | list | this.removeAllSuchThat(list.includes(_)) }
67 removeAllSuchThat { | function |
68 var removedItems = this.class.new;
71 if ( function.value(item, i) )
74 removedItems = removedItems.add(item);
81 ^keys.collect {|index| this[index] }
83 putEach { arg keys, values;
84 // works for ArrayedCollections and Dictionaries
86 values = values.asArray;
87 keys.do { |key, i| this[key] = values.wrapAt(i) } ;
91 this.do {|item2| if (item1 === item2) {^true} };
94 includesEqual { | item1 |
95 this.do {|item2| if (item1 == item2) {^true} };
98 includesAny { | aCollection |
99 aCollection.do { | item | if (this.includes(item)) {^true} };
102 includesAll { | aCollection |
103 aCollection.do { | item | if (this.includes(item).not) {^false} };
110 collect { | function |
111 ^this.collectAs(function, this.species);
113 select { | function |
114 ^this.selectAs(function, this.species);
116 reject { | function |
117 ^this.rejectAs(function, this.species);
119 collectAs { | function, class |
120 var res = class.new(this.size);
121 this.do {|elem, i| res.add(function.value(elem, i)) }
124 selectAs { | function, class |
125 var res = class.new(this.size);
126 this.do {|elem, i| if (function.value(elem, i)) { res = res.add(elem) } }
129 rejectAs { | function, class |
130 var res = class.new(this.size);
132 if (function.value(elem, i).not) {res.add(elem)}
136 detect { | function |
137 this.do {|elem, i| if (function.value(elem, i)) { ^elem } }
140 detectIndex { | function |
141 this.do {|elem, i| if (function.value(elem, i)) { ^i } }
144 doMsg { | selector ... args |
145 this.do {| item | item.performList(selector, args) }
147 collectMsg { | selector ... args |
148 ^this.collect {| item | item.performList(selector, args) }
150 selectMsg { | selector ... args |
151 ^this.select {| item | item.performList(selector, args) }
153 rejectMsg { | selector ... args |
154 ^this.reject {| item | item.performList(selector, args) }
156 detectMsg { | selector ... args |
157 ^this.detect {| item | item.performList(selector, args) }
159 detectIndexMsg { | selector ... args |
160 ^this.detectIndex {| item | item.performList(selector, args) }
162 lastForWhich { | function |
165 if (function.value(elem, i)) {
173 lastIndexForWhich { | function |
176 if (function.value(elem, i)) {
185 inject { | thisValue, function |
186 var nextValue = thisValue;
187 this.do { | item, i |
188 nextValue = function.value(nextValue, item, i);
194 this.do {|elem, i| if (function.value(elem, i)) { sum=sum+1 } }
197 occurrencesOf { | obj |
199 this.do { | elem | if (elem == obj) { sum=sum+1 } }
203 this.do {|elem, i| if (function.value(elem, i)) { ^true } }
207 this.do {|elem, i| if (function.value(elem, i).not) { ^false } }
212 if (function.isNil) { // optimized version if no function
213 this.do { | elem | sum = sum + elem; }
215 this.do {|elem, i| sum = sum + function.value(elem, i); }
220 ^this.sum(function) / this.size;
222 product { | function |
224 if (function.isNil) { // optimized version if no function
225 this.do { | elem | product = product * elem; }
227 this.do {|elem, i| product = product * function.value(elem, i); }
231 sumabs { // sum of the absolute values - used to convert Mikael Laursen's rhythm lists.
234 if (elem.isSequenceableCollection) { elem = elem[0] };
235 sum = sum + elem.abs;
240 maxItem { | function |
241 var maxValue, maxElement;
242 if (function.isNil) { // optimized version if no function
244 if (maxElement.isNil) {
247 if (elem > maxElement) {
254 this.do {|elem, i| var val;
255 if (maxValue.isNil) {
256 maxValue = function.value(elem, i);
259 val = function.value(elem, i);
260 if (val > maxValue) {
269 minItem { | function |
270 var minValue, minElement;
271 if (function.isNil) { // optimized version if no function
273 if (minElement.isNil) {
276 if (elem < minElement) {
283 this.do {|elem, i| var val;
284 if (minValue.isNil) {
285 minValue = function.value(elem, i);
288 val = function.value(elem, i);
289 if (val < minValue) {
299 maxIndex { | function |
300 var maxValue, maxIndex;
301 if (function.isNil) { // optimized version if no function
302 this.do { | elem, index |
303 if (maxValue.isNil) {
307 if (elem > maxValue) {
315 this.do {|elem, i| var val;
316 if (maxValue.isNil) {
317 maxValue = function.value(elem, i);
320 val = function.value(elem, i);
321 if (val > maxValue) {
331 minIndex { | function |
332 var minValue, minIndex;
333 if (function.isNil) { // optimized version if no function
335 if (minValue.isNil) {
339 if (elem < minValue) {
347 this.do {|elem, i| var val;
348 if (minValue.isNil) {
349 minValue = function.value(elem, i);
352 val = function.value(elem, i);
353 if (val < minValue) {
364 maxValue { | function | // must supply a function
365 var maxValue, maxElement;
368 if (maxValue.isNil) {
369 maxValue = function.value(elem, i);
372 val = function.value(elem, i);
373 if (val > maxValue) {
381 minValue { | function |
382 var minValue, minElement;
385 if (minValue.isNil) {
386 minValue = function.value(elem, i);
389 val = function.value(elem, i);
390 if (val < minValue) {
401 // can be used to invert a pitch list about a given axis
402 // [3, 2, 9, 7].invert(11) becomes [ 19, 20, 13, 15 ]
403 // if axis is nil, invert uses the registral center
404 // [3, 2, 9, 7].invert becomes [ 8, 9, 2, 4 ]
405 if(this.isEmpty) { ^this.species.new };
406 if(axis.notNil) { index = axis * 2 } { index = this.minItem + this.maxItem };
411 var result = this.species.new;
413 if (that.includes(item)) {
414 result = result.add(item);
420 var result = this.copy;
422 if (result.includes(item).not) {
423 result = result.add(item);
428 difference { | that |
429 ^this.copy.removeAll(that);
431 symmetricDifference { | that |
432 var result = this.species.new;
434 if (that.includes(item).not) {
435 result = result.add(item);
439 if (this.includes(item).not) {
440 result = result.add(item);
445 isSubsetOf { | that | ^that.includesAll(this) }
447 asArray { ^Array.new(this.size).addAll(this); }
448 asBag { ^Bag.new(this.size).addAll(this); }
449 asList { ^List.new(this.size).addAll(this); }
450 asSet { ^Set.new(this.size).addAll(this); }
451 asSortedList { | function | ^SortedList.new(this.size, function).addAll(this); }
454 var species = this.species;
455 var result = this.asArray.powerset;
456 ^if(species == Array) { result } {
457 result.collectAs({ | item | item.as(species) }, species)
461 flopDict { | unbubble=true |
462 var res, first = true;
464 if(first) { res = dict.class.new; first = false };
465 dict.keysValuesDo { | key, val |
466 res[key] = res[key].add(val)
469 if(unbubble) { res = res.collect(_.unbubble) };
473 histo { arg steps = 100, min, max;
474 var freqs, freqIndex, lastIndex, stepSize, outliers = 0;
475 if(this.isEmpty) { ^this.species.new };
476 min = min ?? { this.minItem };
477 max = max ?? { this.maxItem };
479 freqs = Array.fill(steps, 0);
480 lastIndex = steps - 1;
481 stepSize = steps / (max - min);
484 freqIndex = ((el - min) * stepSize).asInteger;
486 if (freqIndex.inclusivelyBetween(0, lastIndex)) {
487 freqs[freqIndex] = freqs[freqIndex] + 1;
489 // if max is derived from maxItem, count it in:
491 freqs[steps-1] = freqs[steps-1] + 1;
492 } { // else it is an outlier.
493 outliers = outliers + 1;
499 ("histogram :" + outliers + "out of (histogram) range values in collection.").inform;
505 // printAll { this.do { | item | item.postln; }; } // convenience method
506 printAll { |before, after|
507 if (before.isNil and: after.isNil) {
508 this.do { | item | item.postln; };
510 before = before ? ""; after = after ? "";
511 this.do { | item | before.post; item.post; after.postln; };
515 printcsAll { this.do { | item | item.postcs; }; } // convenience method
516 dumpAll { this.do { | item | item.dump; }; } // convenience method
519 if (stream.atLimit) { ^this };
520 stream << this.class.name << "[ " ;
521 this.printItemsOn(stream);
525 if (stream.atLimit) { ^this };
526 stream << this.class.name << "[ " ;
527 this.storeItemsOn(stream);
530 storeItemsOn { | stream |
531 var addComma = false;
533 if (stream.atLimit) { ^this };
534 if (addComma) { stream.comma.space; } { addComma = true };
535 item.storeOn(stream);
538 printItemsOn { | stream |
539 var addComma = false;
541 if (stream.atLimit) { ^this };
542 if (addComma) { stream.comma.space; } { addComma = true };
543 item.printOn(stream);
550 file.putString("SCgf");
551 file.putInt32(1); // file version
552 file.putInt16(this.size); // number of defs in file.
554 this.do { | item | item.writeDef(file); }
557 writeInputSpec { | file, synthDef |
558 this.do { | item | item.writeInputSpec(file, synthDef) };
563 var out = this.detect {|it| it.key.value;};
573 var res = Array.new(this.size * 2);
576 res.add(currentEnvironment[item]);