1 | import { tableChips } from '@analys/table-chips';
|
2 | import { tableDivide } from '@analys/table-divide';
|
3 | import { tableFilter } from '@analys/table-filter';
|
4 | import { tableFind } from '@analys/table-find';
|
5 | import { tableFormula } from '@analys/table-formula';
|
6 | import { tableGroup } from '@analys/table-group';
|
7 | import { slice, shallow } from '@analys/table-init';
|
8 | import { tableJoin } from '@analys/table-join';
|
9 | import { lookupCached, lookup, lookupMany } from '@analys/table-lookup';
|
10 | import { tableAcquire, tableMerge } from '@analys/table-merge';
|
11 | import { tablePivot } from '@analys/table-pivot';
|
12 | import { tableToObject } from '@analys/table-select';
|
13 | import { inferTypes } from '@analys/table-types';
|
14 | import { selectTabularToSamples, tabularToSamples, selectTabular, sortTabularByKeys } from '@analys/tabular';
|
15 | import { NUM_ASC } from '@aryth/comparer';
|
16 | import { DistinctCount, Distinct } from '@aryth/distinct-column';
|
17 | import { distinctByColumn } from '@aryth/distinct-matrix';
|
18 | import { column } from '@vect/column-getter';
|
19 | import { mutate } from '@vect/column-mapper';
|
20 | import { push, unshift, pop, shift, splices as splices$1 } from '@vect/columns-update';
|
21 | import { size, transpose } from '@vect/matrix';
|
22 | import { mapper as mapper$1, mutate as mutate$2, selectMutate } from '@vect/matrix-mapper';
|
23 | import { wind } from '@vect/object-init';
|
24 | import { difference, intersect } from '@vect/vector-algebra';
|
25 | import { mapper, mutate as mutate$1, iterate } from '@vect/vector-mapper';
|
26 | import { splices } from '@vect/vector-update';
|
27 |
|
28 | class Table {
|
29 |
|
30 | head;
|
31 |
|
32 |
|
33 | rows;
|
34 |
|
35 |
|
36 | title;
|
37 |
|
38 |
|
39 | types;
|
40 | |
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 | constructor(head, rows, title, types) {
|
48 | this.head = head || [];
|
49 | this.rows = rows || [];
|
50 | this.title = title || '';
|
51 | this.types = types;
|
52 | }
|
53 |
|
54 | static from(o) {
|
55 | return new Table(o.head || o.banner, o.rows || o.matrix, o.title, o.types);
|
56 | }
|
57 |
|
58 | toSamples(fields) {
|
59 | return fields ? selectTabularToSamples.call(this, fields) : tabularToSamples.call(this);
|
60 | }
|
61 |
|
62 | toObject(mutate = false) {
|
63 | var _this, _this2;
|
64 |
|
65 | return mutate ? (_this = this, slice(_this)) : (_this2 = this, shallow(_this2));
|
66 | }
|
67 |
|
68 | setTitle(title) {
|
69 | return this.title = title, this;
|
70 | }
|
71 |
|
72 | get size() {
|
73 | return size(this.rows);
|
74 | }
|
75 |
|
76 | get ht() {
|
77 | var _this$rows;
|
78 |
|
79 | return (_this$rows = this.rows) === null || _this$rows === void 0 ? void 0 : _this$rows.length;
|
80 | }
|
81 |
|
82 | get wd() {
|
83 | var _this$head;
|
84 |
|
85 | return (_this$head = this.head) === null || _this$head === void 0 ? void 0 : _this$head.length;
|
86 | }
|
87 |
|
88 | get height() {
|
89 | var _this$rows2;
|
90 |
|
91 | return (_this$rows2 = this.rows) === null || _this$rows2 === void 0 ? void 0 : _this$rows2.length;
|
92 | }
|
93 |
|
94 | get width() {
|
95 | var _this$head2;
|
96 |
|
97 | return (_this$head2 = this.head) === null || _this$head2 === void 0 ? void 0 : _this$head2.length;
|
98 | }
|
99 |
|
100 | get columns() {
|
101 | return transpose(this.rows);
|
102 | }
|
103 |
|
104 | cell(x, field) {
|
105 | return x in this.rows ? this.rows[x][this.coin(field)] : undefined;
|
106 | }
|
107 |
|
108 | coin(field) {
|
109 | return this.head.indexOf(field);
|
110 | }
|
111 |
|
112 | columnIndexes(fields) {
|
113 | return fields.map(this.coin, this);
|
114 | }
|
115 |
|
116 | row(field, value, objectify) {
|
117 | const vector = this.rows.find(row => row[this.coin(field)] === value);
|
118 | return vector && objectify ? wind(this.head, vector) : vector;
|
119 | }
|
120 |
|
121 | column(field) {
|
122 | return column(this.rows, this.coin(field), this.height);
|
123 | }
|
124 |
|
125 | setColumn(field, column) {
|
126 | return mutate(this.rows, this.coin(field), (_, i) => column[i], this.height), this;
|
127 | }
|
128 |
|
129 | mutateColumn(field, fn) {
|
130 | return mutate(this.rows, this.coin(field), (x, i) => fn(x, i), this.height), this;
|
131 | }
|
132 |
|
133 | pushRow(row) {
|
134 | return this.rows.push(row), this;
|
135 | }
|
136 |
|
137 | unshiftRow(row) {
|
138 | return this.rows.unshift(row), this;
|
139 | }
|
140 |
|
141 | pushColumn(label, column) {
|
142 | return this.head.push(label), push(this.rows, column), this;
|
143 | }
|
144 |
|
145 | unshiftColumn(label, column) {
|
146 | return this.head.unshift(label), unshift(this.rows, column), this;
|
147 | }
|
148 |
|
149 | popRow() {
|
150 | return this.rows.pop();
|
151 | }
|
152 |
|
153 | shiftRow() {
|
154 | return this.rows.shift();
|
155 | }
|
156 |
|
157 | popColumn() {
|
158 | return [this.head.pop(), pop(this.rows)];
|
159 | }
|
160 |
|
161 | shiftColumn() {
|
162 | return [this.head.shift(), shift(this.rows)];
|
163 | }
|
164 |
|
165 | renameColumn(field, newName) {
|
166 | const ci = this.coin(field);
|
167 | if (ci >= 0) this.head[ci] = newName;
|
168 | return this;
|
169 | }
|
170 |
|
171 | mapHead(fn, {
|
172 | mutate = true
|
173 | } = {}) {
|
174 | return this.boot({
|
175 | head: mapper(this.head, fn)
|
176 | }, mutate);
|
177 | }
|
178 |
|
179 | mutateHead(fn) {
|
180 | return mutate$1(this.head, fn), this;
|
181 | }
|
182 |
|
183 | map(fn, {
|
184 | mutate = true
|
185 | } = {}) {
|
186 | return this.boot({
|
187 | rows: mapper$1(this.rows, fn, this.height, this.width)
|
188 | }, mutate);
|
189 | }
|
190 |
|
191 | mutate(fn, {
|
192 | fields,
|
193 | exclusive
|
194 | } = {}) {
|
195 | if (!fields && !exclusive) return mutate$2(this.rows, fn, this.height, this.width), this;
|
196 | fields = fields ?? this.head;
|
197 | fields = exclusive ? difference(fields, exclusive) : fields;
|
198 | return selectMutate(this.rows, this.columnIndexes(fields), fn, this.height), this;
|
199 | }
|
200 |
|
201 | lookupOne(valueToFind, key, field, cached = true) {
|
202 | return (cached ? lookupCached : lookup).call(this, valueToFind, key, field);
|
203 | }
|
204 |
|
205 | lookupMany(valuesToFind, key, field) {
|
206 | return lookupMany.call(this, valuesToFind, key, field);
|
207 | }
|
208 | |
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 | lookupTable(key, field, objectify = true) {
|
218 | return tableToObject.call(this, key, field, objectify);
|
219 | }
|
220 | |
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 | select(fields, {
|
229 | mutate = false
|
230 | } = {}) {
|
231 | let o = mutate ? this : slice(this);
|
232 | selectTabular.call(o, fields);
|
233 | return mutate ? this : this.copy(o);
|
234 | }
|
235 | |
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 | divideColumn(field, splitter, {
|
246 | fields,
|
247 | mutate = false
|
248 | } = {}) {
|
249 | var _this3;
|
250 |
|
251 | const o = mutate ? this : (_this3 = this, shallow(_this3)),
|
252 | y = this.coin(field);
|
253 | o.head.splice(y, 1, ...(fields ?? splitter(field)));
|
254 | iterate(o.rows, row => row.splice(y, 1, ...splitter(row[y])));
|
255 | return mutate ? this : Table.from(o);
|
256 | }
|
257 | |
258 |
|
259 |
|
260 |
|
261 |
|
262 |
|
263 |
|
264 |
|
265 |
|
266 | proliferateColumn(fieldSpec, {
|
267 | nextTo,
|
268 | mutate = false
|
269 | } = {}) {
|
270 | var _this4, _fieldSpec;
|
271 |
|
272 | if (!Array.isArray(fieldSpec)) fieldSpec = [fieldSpec];
|
273 | const o = mutate ? this : (_this4 = this, shallow(_this4)),
|
274 | {
|
275 | head,
|
276 | rows
|
277 | } = o,
|
278 | y = nextTo ? this.coin(nextTo) + 1 : 0;
|
279 | fieldSpec.forEach(o => o.index = this.coin(o.key));
|
280 |
|
281 | if (((_fieldSpec = fieldSpec) === null || _fieldSpec === void 0 ? void 0 : _fieldSpec.length) === 1) {
|
282 | const [{
|
283 | index,
|
284 | to,
|
285 | as
|
286 | }] = fieldSpec;
|
287 | head.splice(y, 0, as);
|
288 | iterate(rows, row => row.splice(y, 0, to(row[index])));
|
289 | } else {
|
290 | head.splice(y, 0, ...fieldSpec.map(({
|
291 | as
|
292 | }) => as));
|
293 | iterate(rows, row => row.splice(y, 0, ...fieldSpec.map(({
|
294 | index,
|
295 | to
|
296 | }) => to(row[index]))));
|
297 | }
|
298 |
|
299 | return mutate ? this : Table.from(o);
|
300 | }
|
301 | |
302 |
|
303 |
|
304 |
|
305 |
|
306 |
|
307 |
|
308 |
|
309 |
|
310 |
|
311 | insertColumn(newField, column, {
|
312 | nextTo,
|
313 | mutate = false
|
314 | } = {}) {
|
315 | var _this5;
|
316 |
|
317 | const o = mutate ? this : (_this5 = this, shallow(_this5)),
|
318 | y = nextTo ? this.coin(nextTo) + 1 : 0;
|
319 |
|
320 | if (Array.isArray(newField)) {
|
321 | o.head.splice(y, 0, ...newField);
|
322 | iterate(o.rows, (row, i) => row.splice(y, 0, ...column[i]));
|
323 | } else {
|
324 | o.head.splice(y, 0, newField);
|
325 | iterate(o.rows, (row, i) => row.splice(y, 0, column[i]));
|
326 | }
|
327 |
|
328 | return mutate ? this : Table.from(o);
|
329 | }
|
330 | |
331 |
|
332 |
|
333 |
|
334 |
|
335 |
|
336 |
|
337 |
|
338 | deleteColumn(field, {
|
339 | mutate = false
|
340 | } = {}) {
|
341 | var _this6;
|
342 |
|
343 | const o = mutate ? this : (_this6 = this, shallow(_this6));
|
344 | const {
|
345 | head,
|
346 | rows
|
347 | } = o;
|
348 |
|
349 | if (Array.isArray(field)) {
|
350 | const indexes = this.columnIndexes(field).filter(i => i >= 0).sort(NUM_ASC);
|
351 | splices(head, indexes);
|
352 | splices$1(rows, indexes);
|
353 | } else {
|
354 | const index = this.coin(field);
|
355 | head.splice(index, 1);
|
356 | rows.forEach(row => row.splice(index, 1));
|
357 | }
|
358 |
|
359 | return mutate ? this : Table.from(o);
|
360 | }
|
361 |
|
362 | divide(fields, {
|
363 | mutate = false
|
364 | } = {}) {
|
365 | var _this7;
|
366 |
|
367 | const o = mutate ? this : (_this7 = this, shallow(_this7));
|
368 | const {
|
369 | pick,
|
370 | rest
|
371 | } = tableDivide.call(o, fields);
|
372 | return {
|
373 | pick: Table.from(pick),
|
374 | rest: mutate ? this : Table.from(rest)
|
375 | };
|
376 | }
|
377 | |
378 |
|
379 |
|
380 |
|
381 |
|
382 |
|
383 |
|
384 |
|
385 | filter(filterCollection, {
|
386 | mutate = true
|
387 | } = {}) {
|
388 | var _this8;
|
389 |
|
390 | const o = mutate ? this : (_this8 = this, slice(_this8));
|
391 | tableFilter.call(o, filterCollection);
|
392 | return mutate ? this : this.copy(o);
|
393 | }
|
394 | |
395 |
|
396 |
|
397 |
|
398 |
|
399 |
|
400 |
|
401 |
|
402 | find(filter, {
|
403 | mutate = true
|
404 | } = {}) {
|
405 | var _this9;
|
406 |
|
407 | const o = mutate ? this : (_this9 = this, slice(_this9));
|
408 | tableFind.call(o, filter);
|
409 | return mutate ? this : this.copy(o);
|
410 | }
|
411 |
|
412 |
|
413 | distinct(fields, {
|
414 | mutate = true
|
415 | } = {}) {
|
416 | var _this10;
|
417 |
|
418 | const o = mutate ? this : (_this10 = this, slice(_this10));
|
419 |
|
420 | for (let field of fields) o.rows = distinctByColumn.call(o.rows, this.coin(field));
|
421 |
|
422 | return mutate ? this : this.copy(o);
|
423 | }
|
424 | |
425 |
|
426 |
|
427 |
|
428 |
|
429 |
|
430 |
|
431 |
|
432 |
|
433 | distinctOnColumn(field, {
|
434 | count = false,
|
435 | sort = false
|
436 | } = {}) {
|
437 | return count ? DistinctCount(this.coin(field))(this.rows, {
|
438 | l: this.height,
|
439 | sort
|
440 | }) : Distinct(this.coin(field))(this.rows, this.height);
|
441 | }
|
442 | |
443 |
|
444 |
|
445 |
|
446 |
|
447 |
|
448 |
|
449 |
|
450 |
|
451 | sort(field, comparer, {
|
452 | mutate = true
|
453 | } = {}) {
|
454 | var _this11;
|
455 |
|
456 | const y = this.coin(field);
|
457 |
|
458 | const rowComparer = (a, b) => comparer(a[y], b[y]);
|
459 |
|
460 | const o = mutate ? this : (_this11 = this, slice(_this11));
|
461 | o.rows.sort(rowComparer);
|
462 | return mutate ? this : this.copy(o);
|
463 | }
|
464 | |
465 |
|
466 |
|
467 |
|
468 |
|
469 |
|
470 |
|
471 |
|
472 | sortLabel(comparer, {
|
473 | mutate = true
|
474 | } = {}) {
|
475 | var _this12;
|
476 |
|
477 | let o = mutate ? this : (_this12 = this, slice(_this12));
|
478 | sortTabularByKeys.call(o, comparer);
|
479 | return mutate ? this : this.copy(o);
|
480 | }
|
481 |
|
482 | join(another, fields, joinType, fillEmpty) {
|
483 | return Table.from(tableJoin(this, another, fields, joinType, fillEmpty));
|
484 | }
|
485 | |
486 |
|
487 |
|
488 |
|
489 |
|
490 |
|
491 |
|
492 |
|
493 | union(another, {
|
494 | mutate = true
|
495 | } = {}) {
|
496 | const self = mutate ? this : this.copy();
|
497 | const shared = intersect(self.head, another.head);
|
498 |
|
499 | if (shared.length) {
|
500 | for (let label of shared) self.setColumn(label, another.column(label));
|
501 |
|
502 | another = another.deleteColumn(shared, {
|
503 | mutate
|
504 | });
|
505 | }
|
506 |
|
507 | return mutate ? tableAcquire(self, another) : this.copy(tableMerge(self, another));
|
508 | }
|
509 | |
510 |
|
511 |
|
512 |
|
513 |
|
514 |
|
515 |
|
516 |
|
517 |
|
518 |
|
519 | chips(options = {}) {
|
520 | return tableChips.call(this, options);
|
521 | }
|
522 | |
523 |
|
524 |
|
525 |
|
526 |
|
527 |
|
528 |
|
529 |
|
530 |
|
531 |
|
532 | group(options = {}) {
|
533 | return Table.from(tableGroup.call(this, options));
|
534 | }
|
535 | |
536 |
|
537 |
|
538 |
|
539 |
|
540 |
|
541 |
|
542 |
|
543 |
|
544 | formula(formulae, options = {}) {
|
545 | return Table.from(tableFormula.call(this, formulae, options));
|
546 | }
|
547 | |
548 |
|
549 |
|
550 |
|
551 |
|
552 |
|
553 |
|
554 |
|
555 |
|
556 |
|
557 |
|
558 | crosTab(options = {}) {
|
559 | const table = slice(this);
|
560 |
|
561 | if (options.filter) {
|
562 | tableFind.call(table, options.filter);
|
563 | }
|
564 |
|
565 | return tablePivot.call(options, table);
|
566 | }
|
567 |
|
568 | inferTypes({
|
569 | inferType,
|
570 | omitNull = true,
|
571 | mutate = false
|
572 | } = {}) {
|
573 | const types = inferTypes.call(this, {
|
574 | inferType,
|
575 | omitNull
|
576 | });
|
577 | return mutate ? this.types = types : types;
|
578 | }
|
579 |
|
580 |
|
581 |
|
582 | boot({
|
583 | head,
|
584 | rows,
|
585 | types
|
586 | } = {}, mutate = true) {
|
587 | if (mutate) {
|
588 | if (head) this.head = head;
|
589 | if (rows) this.rows = rows;
|
590 | if (types) this.types = types;
|
591 | return this;
|
592 | } else {
|
593 | return this.copy({
|
594 | head,
|
595 | rows,
|
596 | types
|
597 | });
|
598 | }
|
599 | }
|
600 |
|
601 |
|
602 |
|
603 | copy({
|
604 | head,
|
605 | rows,
|
606 | types
|
607 | } = {}) {
|
608 | var _this$types;
|
609 |
|
610 | if (!head) head = this.head.slice();
|
611 | if (!rows) rows = this.rows.map(row => row.slice());
|
612 | if (!types) types = (_this$types = this.types) === null || _this$types === void 0 ? void 0 : _this$types.slice();
|
613 | return new Table(head, rows, this.title, types);
|
614 | }
|
615 |
|
616 | }
|
617 |
|
618 |
|
619 |
|
620 |
|
621 |
|
622 |
|
623 |
|
624 |
|
625 | export { Table };
|