propane 3.11.0-java → 4.0.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.mvn/extensions.xml +1 -1
- data/CHANGELOG.md +2 -0
- data/README.md +5 -5
- data/Rakefile +1 -1
- data/lib/propane/app.rb +2 -2
- data/lib/propane/version.rb +1 -1
- data/lib/propane-4.0.0.jar +0 -0
- data/library/slider/slider.rb +1 -1
- data/pom.rb +8 -8
- data/pom.xml +8 -8
- data/propane.gemspec +3 -3
- data/src/main/java/monkstone/ColorUtil.java +1 -1
- data/src/main/java/monkstone/MathToolModule.java +1 -1
- data/src/main/java/monkstone/PropaneLibrary.java +1 -1
- data/src/main/java/monkstone/fastmath/DegLutTables.java +10 -11
- data/src/main/java/monkstone/fastmath/Deglut.java +1 -1
- data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
- data/src/main/java/monkstone/noise/LICENSE +121 -0
- data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
- data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
- data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
- data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
- data/src/main/java/monkstone/slider/SliderBar.java +1 -1
- data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
- data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
- data/src/main/java/monkstone/vecmath/package-info.java +1 -1
- data/src/main/java/monkstone/vecmath/vec2/Vec2.java +92 -68
- data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -1
- data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
- data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
- data/src/main/java/monkstone/videoevent/package-info.java +1 -1
- data/src/main/java/processing/awt/PGraphicsJava2D.java +0 -1
- data/src/main/java/processing/awt/PImageAWT.java +2 -4
- data/src/main/java/processing/core/PApplet.java +4 -4
- data/src/main/java/processing/core/PImage.java +3025 -3047
- data/src/main/java/processing/core/PMatrix.java +5 -2
- data/src/main/java/processing/data/DoubleDict.java +72 -43
- data/src/main/java/processing/data/DoubleList.java +6 -2
- data/src/main/java/processing/data/FloatDict.java +744 -756
- data/src/main/java/processing/data/FloatList.java +68 -26
- data/src/main/java/processing/data/IntDict.java +72 -45
- data/src/main/java/processing/data/IntList.java +63 -26
- data/src/main/java/processing/data/JSONArray.java +892 -931
- data/src/main/java/processing/data/JSONObject.java +1169 -1262
- data/src/main/java/processing/data/JSONTokener.java +30 -49
- data/src/main/java/processing/data/LongDict.java +699 -712
- data/src/main/java/processing/data/LongList.java +676 -700
- data/src/main/java/processing/data/Sort.java +1 -0
- data/src/main/java/processing/data/Table.java +4040 -3661
- data/src/main/java/processing/data/TableRow.java +16 -0
- data/src/main/java/processing/data/XML.java +1041 -956
- data/src/main/java/processing/event/TouchEvent.java +1 -1
- data/src/main/java/processing/opengl/FontTexture.java +2 -2
- data/src/main/java/processing/opengl/PGraphicsOpenGL.java +15 -18
- data/src/main/java/processing/opengl/PJOGL.java +2 -2
- data/src/main/java/processing/opengl/PShapeOpenGL.java +23 -24
- data/test/vecmath_spec_test.rb +14 -3
- data/vendors/Rakefile +1 -1
- metadata +9 -8
- data/lib/propane-3.11.0.jar +0 -0
@@ -7,7 +7,6 @@ import java.util.NoSuchElementException;
|
|
7
7
|
|
8
8
|
import processing.core.PApplet;
|
9
9
|
|
10
|
-
|
11
10
|
/**
|
12
11
|
* A simple class to use a String as a lookup for an int value.
|
13
12
|
*
|
@@ -17,786 +16,774 @@ import processing.core.PApplet;
|
|
17
16
|
*/
|
18
17
|
public class LongDict {
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
*/
|
75
|
-
public LongDict(String[] keys, long[] values) {
|
76
|
-
if (keys.length != values.length) {
|
77
|
-
throw new IllegalArgumentException("key and value arrays must be the same length");
|
19
|
+
/**
|
20
|
+
* Number of elements in the table
|
21
|
+
*/
|
22
|
+
protected int count;
|
23
|
+
|
24
|
+
protected String[] keys;
|
25
|
+
protected long[] values;
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Internal implementation for faster lookups
|
29
|
+
*/
|
30
|
+
private HashMap<String, Integer> indices = new HashMap<>();
|
31
|
+
|
32
|
+
public LongDict() {
|
33
|
+
count = 0;
|
34
|
+
keys = new String[10];
|
35
|
+
values = new long[10];
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Create a new lookup with a specific size.This is more efficient than not
|
40
|
+
* specifying a size. Use it when you know the rough size of the thing
|
41
|
+
* you're creating.
|
42
|
+
*
|
43
|
+
* @param length
|
44
|
+
* @nowebref
|
45
|
+
*/
|
46
|
+
public LongDict(int length) {
|
47
|
+
count = 0;
|
48
|
+
keys = new String[length];
|
49
|
+
values = new long[length];
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Read a set of entries from a Reader that has each key/value pair on a
|
54
|
+
* single line, separated by a tab.
|
55
|
+
*
|
56
|
+
* @param reader
|
57
|
+
* @nowebref
|
58
|
+
*/
|
59
|
+
public LongDict(BufferedReader reader) {
|
60
|
+
String[] lines = PApplet.loadStrings(reader);
|
61
|
+
keys = new String[lines.length];
|
62
|
+
values = new long[lines.length];
|
63
|
+
|
64
|
+
for (String line : lines) {
|
65
|
+
String[] pieces = PApplet.split(line, '\t');
|
66
|
+
if (pieces.length == 2) {
|
67
|
+
keys[count] = pieces[0];
|
68
|
+
values[count] = PApplet.parseInt(pieces[1]);
|
69
|
+
indices.put(pieces[0], count);
|
70
|
+
count++;
|
71
|
+
}
|
72
|
+
}
|
78
73
|
}
|
79
|
-
this.keys = keys;
|
80
|
-
this.values = values;
|
81
|
-
count = keys.length;
|
82
|
-
for (int i = 0; i < count; i++) {
|
83
|
-
indices.put(keys[i], i);
|
84
|
-
}
|
85
|
-
}
|
86
|
-
|
87
74
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
values[i] = (Integer) pairs[i][1];
|
104
|
-
indices.put(keys[i], i);
|
75
|
+
/**
|
76
|
+
* @param keys
|
77
|
+
* @param values
|
78
|
+
* @nowebref
|
79
|
+
*/
|
80
|
+
public LongDict(String[] keys, long[] values) {
|
81
|
+
if (keys.length != values.length) {
|
82
|
+
throw new IllegalArgumentException("key and value arrays must be the same length");
|
83
|
+
}
|
84
|
+
this.keys = keys;
|
85
|
+
this.values = values;
|
86
|
+
count = keys.length;
|
87
|
+
for (int i = 0; i < count; i++) {
|
88
|
+
indices.put(keys[i], i);
|
89
|
+
}
|
105
90
|
}
|
106
|
-
}
|
107
|
-
|
108
|
-
|
109
|
-
/**
|
110
|
-
* Returns the number of key/value pairs
|
111
|
-
*
|
112
|
-
* @webref intdict:method
|
113
|
-
* @brief Returns the number of key/value pairs
|
114
|
-
*/
|
115
|
-
public int size() {
|
116
|
-
return count;
|
117
|
-
}
|
118
91
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
92
|
+
/**
|
93
|
+
* Constructor to allow (more intuitive) inline initialization, e.g.:
|
94
|
+
* <pre>
|
95
|
+
* new FloatDict(new Object[][] {
|
96
|
+
* { "key1", 1 },
|
97
|
+
* { "key2", 2 }
|
98
|
+
* });
|
99
|
+
* </pre>
|
100
|
+
*
|
101
|
+
* @param pairs
|
102
|
+
*/
|
103
|
+
public LongDict(Object[][] pairs) {
|
104
|
+
count = pairs.length;
|
105
|
+
this.keys = new String[count];
|
106
|
+
this.values = new long[count];
|
107
|
+
for (int i = 0; i < count; i++) {
|
108
|
+
keys[i] = (String) pairs[i][0];
|
109
|
+
values[i] = (Integer) pairs[i][1];
|
110
|
+
indices.put(keys[i], i);
|
111
|
+
}
|
130
112
|
}
|
131
113
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
/**
|
144
|
-
* Remove all entries.
|
145
|
-
*
|
146
|
-
* @webref intdict:method
|
147
|
-
* @brief Remove all entries
|
148
|
-
*/
|
149
|
-
public void clear() {
|
150
|
-
count = 0;
|
151
|
-
indices = new HashMap<>();
|
152
|
-
}
|
153
|
-
|
154
|
-
|
155
|
-
private void resetIndices() {
|
156
|
-
indices = new HashMap<>(count);
|
157
|
-
for (int i = 0; i < count; i++) {
|
158
|
-
indices.put(keys[i], i);
|
114
|
+
/**
|
115
|
+
* Returns the number of key/value pairs
|
116
|
+
*
|
117
|
+
* @return
|
118
|
+
* @webref intdict:method
|
119
|
+
* @brief Returns the number of key/value pairs
|
120
|
+
*/
|
121
|
+
public int size() {
|
122
|
+
return count;
|
159
123
|
}
|
160
|
-
}
|
161
|
-
|
162
|
-
|
163
|
-
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
164
|
-
|
165
124
|
|
166
|
-
|
167
|
-
|
168
|
-
|
125
|
+
/**
|
126
|
+
* Resize the internal data, this can only be used to shrink the
|
127
|
+
* list.Helpful for situations like sorting and then grabbing the top 50
|
128
|
+
* entries.
|
129
|
+
*
|
130
|
+
* @param length
|
131
|
+
*/
|
132
|
+
public void resize(int length) {
|
133
|
+
if (length > count) {
|
134
|
+
throw new IllegalArgumentException("resize() can only be used to shrink the dictionary");
|
135
|
+
}
|
136
|
+
if (length < 1) {
|
137
|
+
throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher");
|
138
|
+
}
|
169
139
|
|
170
|
-
|
171
|
-
|
172
|
-
|
140
|
+
String[] newKeys = new String[length];
|
141
|
+
long[] newValues = new long[length];
|
142
|
+
PApplet.arrayCopy(keys, newKeys, length);
|
143
|
+
PApplet.arrayCopy(values, newValues, length);
|
144
|
+
keys = newKeys;
|
145
|
+
values = newValues;
|
146
|
+
count = length;
|
147
|
+
resetIndices();
|
148
|
+
}
|
149
|
+
|
150
|
+
/**
|
151
|
+
* Remove all entries.
|
152
|
+
*
|
153
|
+
* @webref intdict:method
|
154
|
+
* @brief Remove all entries
|
155
|
+
*/
|
156
|
+
public void clear() {
|
157
|
+
count = 0;
|
158
|
+
indices = new HashMap<>();
|
159
|
+
}
|
160
|
+
|
161
|
+
private void resetIndices() {
|
162
|
+
indices = new HashMap<>(count);
|
163
|
+
for (int i = 0; i < count; i++) {
|
164
|
+
indices.put(keys[i], i);
|
165
|
+
}
|
173
166
|
}
|
174
|
-
}
|
175
|
-
|
176
|
-
|
177
|
-
public Iterable<Entry> entries() {
|
178
|
-
return new Iterable<Entry>() {
|
179
|
-
|
180
|
-
public Iterator<Entry> iterator() {
|
181
|
-
return entryIterator();
|
182
|
-
}
|
183
|
-
};
|
184
|
-
}
|
185
|
-
|
186
|
-
|
187
|
-
public Iterator<Entry> entryIterator() {
|
188
|
-
return new Iterator<Entry>() {
|
189
|
-
int index = -1;
|
190
|
-
|
191
|
-
public void remove() {
|
192
|
-
removeIndex(index);
|
193
|
-
index--;
|
194
|
-
}
|
195
167
|
|
196
|
-
|
197
|
-
|
198
|
-
Entry e = new Entry(keys[index], values[index]);
|
199
|
-
return e;
|
200
|
-
}
|
168
|
+
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
169
|
+
public class Entry {
|
201
170
|
|
202
|
-
|
203
|
-
|
204
|
-
}
|
205
|
-
};
|
206
|
-
}
|
171
|
+
public String key;
|
172
|
+
public long value;
|
207
173
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
public String key(int index) {
|
213
|
-
return keys[index];
|
214
|
-
}
|
215
|
-
|
216
|
-
|
217
|
-
protected void crop() {
|
218
|
-
if (count != keys.length) {
|
219
|
-
keys = PApplet.subset(keys, 0, count);
|
220
|
-
values = PApplet.subset(values, 0, count);
|
174
|
+
Entry(String key, long value) {
|
175
|
+
this.key = key;
|
176
|
+
this.value = value;
|
177
|
+
}
|
221
178
|
}
|
222
|
-
}
|
223
|
-
|
224
|
-
|
225
|
-
public Iterable<String> keys() {
|
226
|
-
return new Iterable<String>() {
|
227
179
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
}
|
232
|
-
};
|
233
|
-
}
|
234
|
-
|
235
|
-
|
236
|
-
// Use this to iterate when you want to be able to remove elements along the way
|
237
|
-
public Iterator<String> keyIterator() {
|
238
|
-
return new Iterator<String>() {
|
239
|
-
int index = -1;
|
240
|
-
|
241
|
-
public void remove() {
|
242
|
-
removeIndex(index);
|
243
|
-
index--;
|
244
|
-
}
|
245
|
-
|
246
|
-
public String next() {
|
247
|
-
return key(++index);
|
248
|
-
}
|
249
|
-
|
250
|
-
public boolean hasNext() {
|
251
|
-
return index+1 < size();
|
252
|
-
}
|
253
|
-
};
|
254
|
-
}
|
180
|
+
public Iterable<Entry> entries() {
|
181
|
+
return () -> entryIterator();
|
182
|
+
}
|
255
183
|
|
184
|
+
public Iterator<Entry> entryIterator() {
|
185
|
+
return new Iterator<Entry>() {
|
186
|
+
int index = -1;
|
256
187
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
*/
|
263
|
-
public String[] keyArray() {
|
264
|
-
crop();
|
265
|
-
return keyArray(null);
|
266
|
-
}
|
188
|
+
@Override
|
189
|
+
public void remove() {
|
190
|
+
removeIndex(index);
|
191
|
+
index--;
|
192
|
+
}
|
267
193
|
|
194
|
+
@Override
|
195
|
+
public Entry next() {
|
196
|
+
++index;
|
197
|
+
Entry e = new Entry(keys[index], values[index]);
|
198
|
+
return e;
|
199
|
+
}
|
268
200
|
|
269
|
-
|
270
|
-
|
271
|
-
|
201
|
+
@Override
|
202
|
+
public boolean hasNext() {
|
203
|
+
return index + 1 < size();
|
204
|
+
}
|
205
|
+
};
|
272
206
|
}
|
273
|
-
System.arraycopy(keys, 0, outgoing, 0, count);
|
274
|
-
return outgoing;
|
275
|
-
}
|
276
207
|
|
208
|
+
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
209
|
+
public String key(int index) {
|
210
|
+
return keys[index];
|
211
|
+
}
|
277
212
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
213
|
+
protected void crop() {
|
214
|
+
if (count != keys.length) {
|
215
|
+
keys = PApplet.subset(keys, 0, count);
|
216
|
+
values = PApplet.subset(values, 0, count);
|
217
|
+
}
|
218
|
+
}
|
282
219
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
*/
|
287
|
-
public Iterable<Long> values() {
|
288
|
-
return new Iterable<Long>() {
|
220
|
+
public Iterable<String> keys() {
|
221
|
+
return () -> keyIterator();
|
222
|
+
}
|
289
223
|
|
290
|
-
|
291
|
-
|
292
|
-
return
|
293
|
-
|
294
|
-
};
|
295
|
-
}
|
224
|
+
// Use this to iterate when you want to be able to remove elements along the way
|
225
|
+
public Iterator<String> keyIterator() {
|
226
|
+
return new Iterator<String>() {
|
227
|
+
int index = -1;
|
296
228
|
|
229
|
+
@Override
|
230
|
+
public void remove() {
|
231
|
+
removeIndex(index);
|
232
|
+
index--;
|
233
|
+
}
|
297
234
|
|
298
|
-
|
299
|
-
|
300
|
-
|
235
|
+
@Override
|
236
|
+
public String next() {
|
237
|
+
return key(++index);
|
238
|
+
}
|
301
239
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
public Long next() {
|
308
|
-
return value(++index);
|
309
|
-
}
|
310
|
-
|
311
|
-
public boolean hasNext() {
|
312
|
-
return index+1 < size();
|
313
|
-
}
|
314
|
-
};
|
315
|
-
}
|
316
|
-
|
317
|
-
|
318
|
-
/**
|
319
|
-
* Create a new array and copy each of the values into it.
|
320
|
-
*
|
321
|
-
* @webref intdict:method
|
322
|
-
* @brief Create a new array and copy each of the values into it
|
323
|
-
*/
|
324
|
-
public int[] valueArray() {
|
325
|
-
crop();
|
326
|
-
return valueArray(null);
|
327
|
-
}
|
328
|
-
|
329
|
-
|
330
|
-
/**
|
331
|
-
* Fill an already-allocated array with the values (more efficient than
|
332
|
-
* creating a new array each time). If 'array' is null, or not the same
|
333
|
-
* size as the number of values, a new array will be allocated and returned.
|
334
|
-
*
|
335
|
-
* @param array values to copy into the array
|
336
|
-
*/
|
337
|
-
public int[] valueArray(int[] array) {
|
338
|
-
if (array == null || array.length != size()) {
|
339
|
-
array = new int[count];
|
340
|
-
}
|
341
|
-
System.arraycopy(values, 0, array, 0, count);
|
342
|
-
return array;
|
343
|
-
}
|
344
|
-
|
345
|
-
|
346
|
-
/**
|
347
|
-
* Return a value for the specified key.
|
348
|
-
*
|
349
|
-
* @webref intdict:method
|
350
|
-
* @brief Return a value for the specified key
|
351
|
-
*/
|
352
|
-
public long get(String key) {
|
353
|
-
int index = index(key);
|
354
|
-
if (index == -1) {
|
355
|
-
throw new IllegalArgumentException("No key named '" + key + "'");
|
356
|
-
}
|
357
|
-
return values[index];
|
358
|
-
}
|
359
|
-
|
360
|
-
|
361
|
-
public long get(String key, long alternate) {
|
362
|
-
int index = index(key);
|
363
|
-
if (index == -1) return alternate;
|
364
|
-
return values[index];
|
365
|
-
}
|
366
|
-
|
367
|
-
|
368
|
-
/**
|
369
|
-
* Create a new key/value pair or change the value of one.
|
370
|
-
*
|
371
|
-
* @webref intdict:method
|
372
|
-
* @brief Create a new key/value pair or change the value of one
|
373
|
-
*/
|
374
|
-
public void set(String key, long amount) {
|
375
|
-
int index = index(key);
|
376
|
-
if (index == -1) {
|
377
|
-
create(key, amount);
|
378
|
-
} else {
|
379
|
-
values[index] = amount;
|
380
|
-
}
|
381
|
-
}
|
382
|
-
|
383
|
-
|
384
|
-
public void setIndex(int index, String key, long value) {
|
385
|
-
if (index < 0 || index >= count) {
|
386
|
-
throw new ArrayIndexOutOfBoundsException(index);
|
387
|
-
}
|
388
|
-
keys[index] = key;
|
389
|
-
values[index] = value;
|
390
|
-
}
|
391
|
-
|
392
|
-
|
393
|
-
/**
|
394
|
-
* @webref intdict:method
|
395
|
-
* @brief Check if a key is a part of the data structure
|
396
|
-
*/
|
397
|
-
public boolean hasKey(String key) {
|
398
|
-
return index(key) != -1;
|
399
|
-
}
|
400
|
-
|
401
|
-
|
402
|
-
/**
|
403
|
-
* Increase the value associated with a specific key by 1.
|
404
|
-
*
|
405
|
-
* @webref intdict:method
|
406
|
-
* @brief Increase the value of a specific key value by 1
|
407
|
-
*/
|
408
|
-
public void increment(String key) {
|
409
|
-
add(key, 1);
|
410
|
-
}
|
411
|
-
|
412
|
-
|
413
|
-
/**
|
414
|
-
* Merge another dictionary into this one. Calling this increment()
|
415
|
-
* since it doesn't make sense in practice for the other dictionary types,
|
416
|
-
* even though it's technically an add().
|
417
|
-
*/
|
418
|
-
public void increment(LongDict dict) {
|
419
|
-
for (int i = 0; i < dict.count; i++) {
|
420
|
-
add(dict.key(i), dict.value(i));
|
421
|
-
}
|
422
|
-
}
|
423
|
-
|
424
|
-
|
425
|
-
/**
|
426
|
-
* @webref intdict:method
|
427
|
-
* @brief Add to a value
|
428
|
-
*/
|
429
|
-
public void add(String key, long amount) {
|
430
|
-
int index = index(key);
|
431
|
-
if (index == -1) {
|
432
|
-
create(key, amount);
|
433
|
-
} else {
|
434
|
-
values[index] += amount;
|
435
|
-
}
|
436
|
-
}
|
437
|
-
|
438
|
-
|
439
|
-
/**
|
440
|
-
* @webref intdict:method
|
441
|
-
* @brief Subtract from a value
|
442
|
-
*/
|
443
|
-
public void sub(String key, long amount) {
|
444
|
-
add(key, -amount);
|
445
|
-
}
|
446
|
-
|
447
|
-
|
448
|
-
/**
|
449
|
-
* @webref intdict:method
|
450
|
-
* @brief Multiply a value
|
451
|
-
*/
|
452
|
-
public void mult(String key, long amount) {
|
453
|
-
int index = index(key);
|
454
|
-
if (index != -1) {
|
455
|
-
values[index] *= amount;
|
240
|
+
@Override
|
241
|
+
public boolean hasNext() {
|
242
|
+
return index + 1 < size();
|
243
|
+
}
|
244
|
+
};
|
456
245
|
}
|
457
|
-
}
|
458
|
-
|
459
246
|
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
247
|
+
/**
|
248
|
+
* Return a copy of the internal keys array.This array can be modified.
|
249
|
+
*
|
250
|
+
* @return
|
251
|
+
* @webref intdict:method
|
252
|
+
* @brief Return a copy of the internal keys array
|
253
|
+
*/
|
254
|
+
public String[] keyArray() {
|
255
|
+
crop();
|
256
|
+
return keyArray(null);
|
468
257
|
}
|
469
|
-
}
|
470
258
|
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
259
|
+
public String[] keyArray(String[] outgoing) {
|
260
|
+
if (outgoing == null || outgoing.length != count) {
|
261
|
+
outgoing = new String[count];
|
262
|
+
}
|
263
|
+
System.arraycopy(keys, 0, outgoing, 0, count);
|
264
|
+
return outgoing;
|
265
|
+
}
|
266
|
+
|
267
|
+
public long value(int index) {
|
268
|
+
return values[index];
|
269
|
+
}
|
270
|
+
|
271
|
+
/**
|
272
|
+
* @return
|
273
|
+
* @webref intdict:method
|
274
|
+
* @brief Return the internal array being used to store the values
|
275
|
+
*/
|
276
|
+
public Iterable<Long> values() {
|
277
|
+
return () -> valueIterator();
|
278
|
+
}
|
279
|
+
|
280
|
+
public Iterator<Long> valueIterator() {
|
281
|
+
return new Iterator<Long>() {
|
282
|
+
int index = -1;
|
283
|
+
|
284
|
+
@Override
|
285
|
+
public void remove() {
|
286
|
+
removeIndex(index);
|
287
|
+
index--;
|
288
|
+
}
|
289
|
+
|
290
|
+
@Override
|
291
|
+
public Long next() {
|
292
|
+
return value(++index);
|
293
|
+
}
|
294
|
+
|
295
|
+
@Override
|
296
|
+
public boolean hasNext() {
|
297
|
+
return index + 1 < size();
|
298
|
+
}
|
299
|
+
};
|
300
|
+
}
|
301
|
+
|
302
|
+
/**
|
303
|
+
* Create a new array and copy each of the values into it.
|
304
|
+
*
|
305
|
+
* @return
|
306
|
+
* @webref intdict:method
|
307
|
+
* @brief Create a new array and copy each of the values into it
|
308
|
+
*/
|
309
|
+
public int[] valueArray() {
|
310
|
+
crop();
|
311
|
+
return valueArray(null);
|
312
|
+
}
|
313
|
+
|
314
|
+
/**
|
315
|
+
* Fill an already-allocated array with the values (more efficient than
|
316
|
+
* creating a new array each time).If 'array' is null, or not the same size
|
317
|
+
as the number of values, a new array will be allocated and returned.
|
318
|
+
*
|
319
|
+
* @param array values to copy into the array
|
320
|
+
* @return
|
321
|
+
*/
|
322
|
+
public int[] valueArray(int[] array) {
|
323
|
+
if (array == null || array.length != size()) {
|
324
|
+
array = new int[count];
|
325
|
+
}
|
326
|
+
System.arraycopy(values, 0, array, 0, count);
|
327
|
+
return array;
|
328
|
+
}
|
329
|
+
|
330
|
+
/**
|
331
|
+
* Return a value for the specified key.
|
332
|
+
*
|
333
|
+
* @param key
|
334
|
+
* @return
|
335
|
+
* @webref intdict:method
|
336
|
+
* @brief Return a value for the specified key
|
337
|
+
*/
|
338
|
+
public long get(String key) {
|
339
|
+
int index = index(key);
|
340
|
+
if (index == -1) {
|
341
|
+
throw new IllegalArgumentException("No key named '" + key + "'");
|
342
|
+
}
|
343
|
+
return values[index];
|
478
344
|
}
|
479
|
-
}
|
480
345
|
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
346
|
+
public long get(String key, long alternate) {
|
347
|
+
int index = index(key);
|
348
|
+
if (index == -1) {
|
349
|
+
return alternate;
|
350
|
+
}
|
351
|
+
return values[index];
|
352
|
+
}
|
353
|
+
|
354
|
+
/**
|
355
|
+
* Create a new key/value pair or change the value of one.
|
356
|
+
*
|
357
|
+
* @param key
|
358
|
+
* @param amount
|
359
|
+
* @webref intdict:method
|
360
|
+
* @brief Create a new key/value pair or change the value of one
|
361
|
+
*/
|
362
|
+
public void set(String key, long amount) {
|
363
|
+
int index = index(key);
|
364
|
+
if (index == -1) {
|
365
|
+
create(key, amount);
|
366
|
+
} else {
|
367
|
+
values[index] = amount;
|
368
|
+
}
|
494
369
|
}
|
495
|
-
return index;
|
496
|
-
}
|
497
370
|
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
371
|
+
public void setIndex(int index, String key, long value) {
|
372
|
+
if (index < 0 || index >= count) {
|
373
|
+
throw new ArrayIndexOutOfBoundsException(index);
|
374
|
+
}
|
375
|
+
keys[index] = key;
|
376
|
+
values[index] = value;
|
377
|
+
}
|
378
|
+
|
379
|
+
/**
|
380
|
+
* @param key
|
381
|
+
* @return
|
382
|
+
* @webref intdict:method
|
383
|
+
* @brief Check if a key is a part of the data structure
|
384
|
+
*/
|
385
|
+
public boolean hasKey(String key) {
|
386
|
+
return index(key) != -1;
|
387
|
+
}
|
388
|
+
|
389
|
+
/**
|
390
|
+
* Increase the value associated with a specific key by 1.
|
391
|
+
*
|
392
|
+
* @param key
|
393
|
+
* @webref intdict:method
|
394
|
+
* @brief Increase the value of a specific key value by 1
|
395
|
+
*/
|
396
|
+
public void increment(String key) {
|
397
|
+
add(key, 1);
|
398
|
+
}
|
399
|
+
|
400
|
+
/**
|
401
|
+
* Merge another dictionary into this one.Calling this increment() since it
|
402
|
+
doesn't make sense in practice for the other dictionary types, even
|
403
|
+
though it's technically an add().
|
404
|
+
* @param dict
|
405
|
+
*/
|
406
|
+
public void increment(LongDict dict) {
|
407
|
+
for (int i = 0; i < dict.count; i++) {
|
408
|
+
add(dict.key(i), dict.value(i));
|
409
|
+
}
|
505
410
|
}
|
506
|
-
return keys[index];
|
507
|
-
}
|
508
|
-
|
509
|
-
|
510
|
-
// return the minimum value, or throw an error if there are no values
|
511
|
-
public long minValue() {
|
512
|
-
checkMinMax("minValue");
|
513
|
-
return values[minIndex()];
|
514
|
-
}
|
515
|
-
|
516
411
|
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
412
|
+
/**
|
413
|
+
* @param key
|
414
|
+
* @param amount
|
415
|
+
* @webref intdict:method
|
416
|
+
* @brief Add to a value
|
417
|
+
*/
|
418
|
+
public void add(String key, long amount) {
|
419
|
+
int index = index(key);
|
420
|
+
if (index == -1) {
|
421
|
+
create(key, amount);
|
422
|
+
} else {
|
423
|
+
values[index] += amount;
|
424
|
+
}
|
530
425
|
}
|
531
|
-
return index;
|
532
|
-
}
|
533
|
-
|
534
426
|
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
427
|
+
/**
|
428
|
+
* @param key
|
429
|
+
* @param amount
|
430
|
+
* @webref intdict:method
|
431
|
+
* @brief Subtract from a value
|
432
|
+
*/
|
433
|
+
public void sub(String key, long amount) {
|
434
|
+
add(key, -amount);
|
435
|
+
}
|
436
|
+
|
437
|
+
/**
|
438
|
+
* @param key
|
439
|
+
* @param amount
|
440
|
+
* @webref intdict:method
|
441
|
+
* @brief Multiply a value
|
442
|
+
*/
|
443
|
+
public void mult(String key, long amount) {
|
444
|
+
int index = index(key);
|
445
|
+
if (index != -1) {
|
446
|
+
values[index] *= amount;
|
447
|
+
}
|
541
448
|
}
|
542
|
-
return keys[index];
|
543
|
-
}
|
544
449
|
|
450
|
+
/**
|
451
|
+
* @param key
|
452
|
+
* @param amount
|
453
|
+
* @webref intdict:method
|
454
|
+
* @brief Divide a value
|
455
|
+
*/
|
456
|
+
public void div(String key, long amount) {
|
457
|
+
int index = index(key);
|
458
|
+
if (index != -1) {
|
459
|
+
values[index] /= amount;
|
460
|
+
}
|
461
|
+
}
|
545
462
|
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
463
|
+
private void checkMinMax(String functionName) {
|
464
|
+
if (count == 0) {
|
465
|
+
String msg
|
466
|
+
= String.format("Cannot use %s() on an empty %s.",
|
467
|
+
functionName, getClass().getSimpleName());
|
468
|
+
throw new RuntimeException(msg);
|
469
|
+
}
|
470
|
+
}
|
551
471
|
|
472
|
+
// return the index of the minimum value
|
473
|
+
public int minIndex() {
|
474
|
+
//checkMinMax("minIndex");
|
475
|
+
if (count == 0) {
|
476
|
+
return -1;
|
477
|
+
}
|
552
478
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
479
|
+
int index = 0;
|
480
|
+
long value = values[0];
|
481
|
+
for (int i = 1; i < count; i++) {
|
482
|
+
if (values[i] < value) {
|
483
|
+
index = i;
|
484
|
+
value = values[i];
|
485
|
+
}
|
486
|
+
}
|
487
|
+
return index;
|
557
488
|
}
|
558
|
-
return sum;
|
559
|
-
}
|
560
489
|
|
490
|
+
// return the key for the minimum value
|
491
|
+
public String minKey() {
|
492
|
+
checkMinMax("minKey");
|
493
|
+
int index = minIndex();
|
494
|
+
if (index == -1) {
|
495
|
+
return null;
|
496
|
+
}
|
497
|
+
return keys[index];
|
498
|
+
}
|
561
499
|
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
500
|
+
// return the minimum value, or throw an error if there are no values
|
501
|
+
public long minValue() {
|
502
|
+
checkMinMax("minValue");
|
503
|
+
return values[minIndex()];
|
504
|
+
}
|
567
505
|
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
506
|
+
// return the index of the max value
|
507
|
+
public int maxIndex() {
|
508
|
+
//checkMinMax("maxIndex");
|
509
|
+
if (count == 0) {
|
510
|
+
return -1;
|
511
|
+
}
|
512
|
+
int index = 0;
|
513
|
+
long value = values[0];
|
514
|
+
for (int i = 1; i < count; i++) {
|
515
|
+
if (values[i] > value) {
|
516
|
+
index = i;
|
517
|
+
value = values[i];
|
518
|
+
}
|
519
|
+
}
|
520
|
+
return index;
|
521
|
+
}
|
522
|
+
|
523
|
+
/**
|
524
|
+
* return the key corresponding to the maximum value or null if no entries
|
525
|
+
* @return
|
526
|
+
*/
|
527
|
+
public String maxKey() {
|
528
|
+
//checkMinMax("maxKey");
|
529
|
+
int index = maxIndex();
|
530
|
+
if (index == -1) {
|
531
|
+
return null;
|
532
|
+
}
|
533
|
+
return keys[index];
|
572
534
|
}
|
573
|
-
indices.put(what, Integer.valueOf(count));
|
574
|
-
keys[count] = what;
|
575
|
-
values[count] = much;
|
576
|
-
count++;
|
577
|
-
}
|
578
535
|
|
536
|
+
// return the maximum value or throw an error if zero length
|
537
|
+
public long maxValue() {
|
538
|
+
checkMinMax("maxIndex");
|
539
|
+
return values[maxIndex()];
|
540
|
+
}
|
579
541
|
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
if (index == -1) {
|
587
|
-
throw new NoSuchElementException("'" + key + "' not found");
|
542
|
+
public long sum() {
|
543
|
+
long sum = 0;
|
544
|
+
for (int i = 0; i < count; i++) {
|
545
|
+
sum += values[i];
|
546
|
+
}
|
547
|
+
return sum;
|
588
548
|
}
|
589
|
-
long value = values[index];
|
590
|
-
removeIndex(index);
|
591
|
-
return value;
|
592
|
-
}
|
593
549
|
|
550
|
+
public int index(String what) {
|
551
|
+
Integer found = indices.get(what);
|
552
|
+
return (found == null) ? -1 : found;
|
553
|
+
}
|
594
554
|
|
595
|
-
|
596
|
-
|
597
|
-
|
555
|
+
protected void create(String what, long much) {
|
556
|
+
if (count == keys.length) {
|
557
|
+
keys = PApplet.expand(keys);
|
558
|
+
values = PApplet.expand(values);
|
559
|
+
}
|
560
|
+
indices.put(what, count);
|
561
|
+
keys[count] = what;
|
562
|
+
values[count] = much;
|
563
|
+
count++;
|
598
564
|
}
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
565
|
+
|
566
|
+
/**
|
567
|
+
* @param key
|
568
|
+
* @return
|
569
|
+
* @webref intdict:method
|
570
|
+
* @brief Remove a key/value pair
|
571
|
+
*/
|
572
|
+
public long remove(String key) {
|
573
|
+
int index = index(key);
|
574
|
+
if (index == -1) {
|
575
|
+
throw new NoSuchElementException("'" + key + "' not found");
|
576
|
+
}
|
577
|
+
long value = values[index];
|
578
|
+
removeIndex(index);
|
579
|
+
return value;
|
605
580
|
}
|
606
|
-
count--;
|
607
|
-
keys[count] = null;
|
608
|
-
values[count] = 0;
|
609
|
-
return value;
|
610
|
-
}
|
611
581
|
|
582
|
+
public long removeIndex(int index) {
|
583
|
+
if (index < 0 || index >= count) {
|
584
|
+
throw new ArrayIndexOutOfBoundsException(index);
|
585
|
+
}
|
586
|
+
long value = values[index];
|
587
|
+
indices.remove(keys[index]);
|
588
|
+
for (int i = index; i < count - 1; i++) {
|
589
|
+
keys[i] = keys[i + 1];
|
590
|
+
values[i] = values[i + 1];
|
591
|
+
indices.put(keys[i], i);
|
592
|
+
}
|
593
|
+
count--;
|
594
|
+
keys[count] = null;
|
595
|
+
values[count] = 0;
|
596
|
+
return value;
|
597
|
+
}
|
612
598
|
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
599
|
+
public void swap(int a, int b) {
|
600
|
+
String tkey = keys[a];
|
601
|
+
long tvalue = values[a];
|
602
|
+
keys[a] = keys[b];
|
603
|
+
values[a] = values[b];
|
604
|
+
keys[b] = tkey;
|
605
|
+
values[b] = tvalue;
|
620
606
|
|
621
607
|
// indices.put(keys[a], Integer.valueOf(a));
|
622
608
|
// indices.put(keys[b], Integer.valueOf(b));
|
623
|
-
}
|
624
|
-
|
625
|
-
|
626
|
-
/**
|
627
|
-
* Sort the keys alphabetically (ignoring case). Uses the value as a
|
628
|
-
* tie-breaker (only really possible with a key that has a case change).
|
629
|
-
*
|
630
|
-
* @webref intdict:method
|
631
|
-
* @brief Sort the keys alphabetically
|
632
|
-
*/
|
633
|
-
public void sortKeys() {
|
634
|
-
sortImpl(true, false, true);
|
635
|
-
}
|
636
|
-
|
637
|
-
/**
|
638
|
-
* Sort the keys alphabetically in reverse (ignoring case). Uses the value as a
|
639
|
-
* tie-breaker (only really possible with a key that has a case change).
|
640
|
-
*
|
641
|
-
* @webref intdict:method
|
642
|
-
* @brief Sort the keys alphabetically in reverse
|
643
|
-
*/
|
644
|
-
public void sortKeysReverse() {
|
645
|
-
sortImpl(true, true, true);
|
646
|
-
}
|
647
|
-
|
648
|
-
|
649
|
-
/**
|
650
|
-
* Sort by values in ascending order. The smallest value will be at [0].
|
651
|
-
*
|
652
|
-
* @webref intdict:method
|
653
|
-
* @brief Sort by values in ascending order
|
654
|
-
*/
|
655
|
-
public void sortValues() {
|
656
|
-
sortValues(true);
|
657
|
-
}
|
658
|
-
|
659
|
-
|
660
|
-
/**
|
661
|
-
* Set true to ensure that the order returned is identical. Slightly
|
662
|
-
* slower because the tie-breaker for identical values compares the keys.
|
663
|
-
* @param stable
|
664
|
-
*/
|
665
|
-
public void sortValues(boolean stable) {
|
666
|
-
sortImpl(false, false, stable);
|
667
|
-
}
|
668
|
-
|
669
|
-
|
670
|
-
/**
|
671
|
-
* Sort by values in descending order. The largest value will be at [0].
|
672
|
-
*
|
673
|
-
* @webref intdict:method
|
674
|
-
* @brief Sort by values in descending order
|
675
|
-
*/
|
676
|
-
public void sortValuesReverse() {
|
677
|
-
sortValuesReverse(true);
|
678
|
-
}
|
679
|
-
|
680
|
-
|
681
|
-
public void sortValuesReverse(boolean stable) {
|
682
|
-
sortImpl(false, true, stable);
|
683
|
-
}
|
684
|
-
|
685
|
-
|
686
|
-
protected void sortImpl(final boolean useKeys, final boolean reverse,
|
687
|
-
final boolean stable) {
|
688
|
-
Sort s = new Sort() {
|
689
|
-
@Override
|
690
|
-
public int size() {
|
691
|
-
return count;
|
692
|
-
}
|
693
|
-
|
694
|
-
@Override
|
695
|
-
public int compare(int a, int b) {
|
696
|
-
long diff = 0;
|
697
|
-
if (useKeys) {
|
698
|
-
diff = keys[a].compareToIgnoreCase(keys[b]);
|
699
|
-
if (diff == 0) {
|
700
|
-
diff = values[a] - values[b];
|
701
|
-
}
|
702
|
-
} else { // sort values
|
703
|
-
diff = values[a] - values[b];
|
704
|
-
if (diff == 0 && stable) {
|
705
|
-
diff = keys[a].compareToIgnoreCase(keys[b]);
|
706
|
-
}
|
707
|
-
}
|
708
|
-
if (diff == 0) {
|
709
|
-
return 0;
|
710
|
-
} else if (reverse) {
|
711
|
-
return diff < 0 ? 1 : -1;
|
712
|
-
} else {
|
713
|
-
return diff < 0 ? -1 : 1;
|
714
|
-
}
|
715
|
-
}
|
716
|
-
|
717
|
-
@Override
|
718
|
-
public void swap(int a, int b) {
|
719
|
-
LongDict.this.swap(a, b);
|
720
|
-
}
|
721
|
-
};
|
722
|
-
s.run();
|
723
|
-
|
724
|
-
// Set the indices after sort/swaps (performance fix 160411)
|
725
|
-
resetIndices();
|
726
|
-
}
|
727
|
-
|
728
|
-
|
729
|
-
/**
|
730
|
-
* Sum all of the values in this dictionary, then return a new FloatDict of
|
731
|
-
* each key, divided by the total sum. The total for all values will be ~1.0.
|
732
|
-
* @return an IntDict with the original keys, mapped to their pct of the total
|
733
|
-
*/
|
734
|
-
public FloatDict getPercent() {
|
735
|
-
double sum = sum(); // a little more accuracy
|
736
|
-
FloatDict outgoing = new FloatDict();
|
737
|
-
for (int i = 0; i < size(); i++) {
|
738
|
-
double percent = value(i) / sum;
|
739
|
-
outgoing.set(key(i), (float) percent);
|
740
609
|
}
|
741
|
-
return outgoing;
|
742
|
-
}
|
743
610
|
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
611
|
+
/**
|
612
|
+
* Sort the keys alphabetically (ignoring case). Uses the value as a
|
613
|
+
* tie-breaker (only really possible with a key that has a case change).
|
614
|
+
*
|
615
|
+
* @webref intdict:method
|
616
|
+
* @brief Sort the keys alphabetically
|
617
|
+
*/
|
618
|
+
public void sortKeys() {
|
619
|
+
sortImpl(true, false, true);
|
620
|
+
}
|
621
|
+
|
622
|
+
/**
|
623
|
+
* Sort the keys alphabetically in reverse (ignoring case). Uses the value
|
624
|
+
* as a tie-breaker (only really possible with a key that has a case
|
625
|
+
* change).
|
626
|
+
*
|
627
|
+
* @webref intdict:method
|
628
|
+
* @brief Sort the keys alphabetically in reverse
|
629
|
+
*/
|
630
|
+
public void sortKeysReverse() {
|
631
|
+
sortImpl(true, true, true);
|
632
|
+
}
|
633
|
+
|
634
|
+
/**
|
635
|
+
* Sort by values in ascending order. The smallest value will be at [0].
|
636
|
+
*
|
637
|
+
* @webref intdict:method
|
638
|
+
* @brief Sort by values in ascending order
|
639
|
+
*/
|
640
|
+
public void sortValues() {
|
641
|
+
sortValues(true);
|
642
|
+
}
|
643
|
+
|
644
|
+
/**
|
645
|
+
* Set true to ensure that the order returned is identical. Slightly slower
|
646
|
+
* because the tie-breaker for identical values compares the keys.
|
647
|
+
*
|
648
|
+
* @param stable
|
649
|
+
*/
|
650
|
+
public void sortValues(boolean stable) {
|
651
|
+
sortImpl(false, false, stable);
|
652
|
+
}
|
653
|
+
|
654
|
+
/**
|
655
|
+
* Sort by values in descending order. The largest value will be at [0].
|
656
|
+
*
|
657
|
+
* @webref intdict:method
|
658
|
+
* @brief Sort by values in descending order
|
659
|
+
*/
|
660
|
+
public void sortValuesReverse() {
|
661
|
+
sortValuesReverse(true);
|
662
|
+
}
|
663
|
+
|
664
|
+
public void sortValuesReverse(boolean stable) {
|
665
|
+
sortImpl(false, true, stable);
|
666
|
+
}
|
667
|
+
|
668
|
+
protected void sortImpl(final boolean useKeys, final boolean reverse,
|
669
|
+
final boolean stable) {
|
670
|
+
Sort s = new Sort() {
|
671
|
+
@Override
|
672
|
+
public int size() {
|
673
|
+
return count;
|
674
|
+
}
|
675
|
+
|
676
|
+
@Override
|
677
|
+
public int compare(int a, int b) {
|
678
|
+
long diff = 0;
|
679
|
+
if (useKeys) {
|
680
|
+
diff = keys[a].compareToIgnoreCase(keys[b]);
|
681
|
+
if (diff == 0) {
|
682
|
+
diff = values[a] - values[b];
|
683
|
+
}
|
684
|
+
} else { // sort values
|
685
|
+
diff = values[a] - values[b];
|
686
|
+
if (diff == 0 && stable) {
|
687
|
+
diff = keys[a].compareToIgnoreCase(keys[b]);
|
688
|
+
}
|
689
|
+
}
|
690
|
+
if (diff == 0) {
|
691
|
+
return 0;
|
692
|
+
} else if (reverse) {
|
693
|
+
return diff < 0 ? 1 : -1;
|
694
|
+
} else {
|
695
|
+
return diff < 0 ? -1 : 1;
|
696
|
+
}
|
697
|
+
}
|
698
|
+
|
699
|
+
@Override
|
700
|
+
public void swap(int a, int b) {
|
701
|
+
LongDict.this.swap(a, b);
|
702
|
+
}
|
703
|
+
};
|
704
|
+
s.run();
|
705
|
+
|
706
|
+
// Set the indices after sort/swaps (performance fix 160411)
|
707
|
+
resetIndices();
|
708
|
+
}
|
709
|
+
|
710
|
+
/**
|
711
|
+
* Sum all of the values in this dictionary, then return a new FloatDict of
|
712
|
+
* each key, divided by the total sum. The total for all values will be
|
713
|
+
* ~1.0.
|
714
|
+
*
|
715
|
+
* @return an IntDict with the original keys, mapped to their pct of the
|
716
|
+
* total
|
717
|
+
*/
|
718
|
+
public FloatDict getPercent() {
|
719
|
+
double sum = sum(); // a little more accuracy
|
720
|
+
FloatDict outgoing = new FloatDict();
|
721
|
+
for (int i = 0; i < size(); i++) {
|
722
|
+
double percent = value(i) / sum;
|
723
|
+
outgoing.set(key(i), (float) percent);
|
724
|
+
}
|
725
|
+
return outgoing;
|
726
|
+
}
|
727
|
+
|
728
|
+
/**
|
729
|
+
* Returns a duplicate copy of this object.
|
730
|
+
*
|
731
|
+
* @return
|
732
|
+
*/
|
733
|
+
public LongDict copy() {
|
734
|
+
LongDict outgoing = new LongDict(count);
|
735
|
+
System.arraycopy(keys, 0, outgoing.keys, 0, count);
|
736
|
+
System.arraycopy(values, 0, outgoing.values, 0, count);
|
737
|
+
for (int i = 0; i < count; i++) {
|
738
|
+
outgoing.indices.put(keys[i], i);
|
739
|
+
}
|
740
|
+
outgoing.count = count;
|
741
|
+
return outgoing;
|
752
742
|
}
|
753
|
-
outgoing.count = count;
|
754
|
-
return outgoing;
|
755
|
-
}
|
756
|
-
|
757
743
|
|
758
|
-
|
759
|
-
|
760
|
-
|
744
|
+
public void print() {
|
745
|
+
for (int i = 0; i < size(); i++) {
|
746
|
+
System.out.println(keys[i] + " = " + values[i]);
|
747
|
+
}
|
761
748
|
}
|
762
|
-
}
|
763
|
-
|
764
|
-
|
765
|
-
/**
|
766
|
-
* Save tab-delimited entries to a file (TSV format, UTF-8 encoding)
|
767
|
-
*/
|
768
|
-
public void save(File file) {
|
769
|
-
PrintWriter writer = PApplet.createWriter(file);
|
770
|
-
write(writer);
|
771
|
-
writer.close();
|
772
|
-
}
|
773
749
|
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
750
|
+
/**
|
751
|
+
* Save tab-delimited entries to a file (TSV format, UTF-8 encoding)
|
752
|
+
* @param file
|
753
|
+
*/
|
754
|
+
public void save(File file) {
|
755
|
+
try (PrintWriter writer = PApplet.createWriter(file)) {
|
756
|
+
write(writer);
|
757
|
+
}
|
781
758
|
}
|
782
|
-
writer.flush();
|
783
|
-
}
|
784
759
|
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
760
|
+
/**
|
761
|
+
* Write tab-delimited entries to a PrintWriter
|
762
|
+
*
|
763
|
+
* @param writer
|
764
|
+
*/
|
765
|
+
public void write(PrintWriter writer) {
|
766
|
+
for (int i = 0; i < count; i++) {
|
767
|
+
writer.println(keys[i] + "\t" + values[i]);
|
768
|
+
}
|
769
|
+
writer.flush();
|
770
|
+
}
|
771
|
+
|
772
|
+
/**
|
773
|
+
* Return this dictionary as a String in JSON format.
|
774
|
+
*
|
775
|
+
* @return
|
776
|
+
*/
|
777
|
+
public String toJSON() {
|
778
|
+
StringList items = new StringList();
|
779
|
+
for (int i = 0; i < count; i++) {
|
780
|
+
items.append(JSONObject.quote(keys[i]) + ": " + values[i]);
|
781
|
+
}
|
782
|
+
return "{ " + items.join(", ") + " }";
|
793
783
|
}
|
794
|
-
return "{ " + items.join(", ") + " }";
|
795
|
-
}
|
796
|
-
|
797
784
|
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
785
|
+
@Override
|
786
|
+
public String toString() {
|
787
|
+
return getClass().getSimpleName() + " size=" + size() + " " + toJSON();
|
788
|
+
}
|
802
789
|
}
|