UNPKG

1.73 kBJavaScriptView Raw
1import {Transform, ingest} from 'vega-dataflow';
2import {inherits, truthy} from 'vega-util';
3
4/**
5 * Perform a cross-product of a tuple stream with itself.
6 * @constructor
7 * @param {object} params - The parameters for this operator.
8 * @param {function(object):boolean} [params.filter] - An optional filter
9 * function for selectively including tuples in the cross product.
10 * @param {Array<string>} [params.as] - The names of the output fields.
11 */
12export default function Cross(params) {
13 Transform.call(this, null, params);
14}
15
16Cross.Definition = {
17 'type': 'Cross',
18 'metadata': {'generates': true},
19 'params': [
20 { 'name': 'filter', 'type': 'expr' },
21 { 'name': 'as', 'type': 'string', 'array': true, 'length': 2, 'default': ['a', 'b'] }
22 ]
23};
24
25inherits(Cross, Transform, {
26 transform(_, pulse) {
27 const out = pulse.fork(pulse.NO_SOURCE),
28 as = _.as || ['a', 'b'],
29 a = as[0], b = as[1],
30 reset = !this.value
31 || pulse.changed(pulse.ADD_REM)
32 || _.modified('as')
33 || _.modified('filter');
34
35 let data = this.value;
36 if (reset) {
37 if (data) out.rem = data;
38 data = pulse.materialize(pulse.SOURCE).source;
39 out.add = this.value = cross(data, a, b, _.filter || truthy);
40 } else {
41 out.mod = data;
42 }
43
44 out.source = this.value;
45 return out.modifies(as);
46 }
47});
48
49function cross(input, a, b, filter) {
50 var data = [],
51 t = {},
52 n = input.length,
53 i = 0,
54 j, left;
55
56 for (; i<n; ++i) {
57 t[a] = left = input[i];
58 for (j=0; j<n; ++j) {
59 t[b] = input[j];
60 if (filter(t)) {
61 data.push(ingest(t));
62 t = {};
63 t[a] = left;
64 }
65 }
66 }
67
68 return data;
69}