From bce8923cee9d8d3820a8d48a5773b69197553879 Mon Sep 17 00:00:00 2001 From: Thomas Wilkerling Date: Fri, 4 Jun 2021 22:35:26 +0200 Subject: [PATCH] stretch score to full resolution + improve intersection --- dist/flexsearch.bundle.js | 54 ++-- dist/flexsearch.compact.js | 40 +-- dist/flexsearch.debug.js | 428 ++++++++++++++++---------------- dist/flexsearch.es5.js | 60 ++--- dist/flexsearch.light.js | 22 +- src/index.js | 103 ++++---- src/intersect.js | 493 +++++++++++++++++++------------------ 7 files changed, 615 insertions(+), 585 deletions(-) diff --git a/dist/flexsearch.bundle.js b/dist/flexsearch.bundle.js index 3e8c70f..c3681d0 100644 --- a/dist/flexsearch.bundle.js +++ b/dist/flexsearch.bundle.js @@ -5,30 +5,30 @@ * Licence: Apache-2.0 * https://github.com/nextapps-de/flexsearch */ -(function _f(self){'use strict';try{if(module)self=module}catch(e){}self._factory=_f;var r;function v(a){return"undefined"!==typeof a?a:!0}function w(a){const b=Array(a);for(let c=0;c=this.A&&(m||!u[k])){var f=df;h--)if(h-f>=this.A){var l=d+e= -this.A&&M(this,u,g,d+e=this.A&&M(this,u,g,f,a,c);break;default:if(M(this,u,k,f,a,c),m&&1=this.A&&!g[k]){g[k]=1;const p=this.F&&k>f;M(this,t,p?f:k,h+d=this.A&&!c[t])if(this.s||f||this.map[t])l[u++]=t,c[t]=1;else return d;a=l;e=a.length}if(!e)return d;b||(b=100);h=this.depth&&1=d)))break;if(n){if(f)return ta(l,d,0);b[b.length]=l;return}}return!c&&l}function ta(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a} -function ua(a,b,c,d){c?(d=d&&b>c,a=(a=a[d?b:c])&&a[d?c:b]):a=a[b];return a}r.contain=function(a){return!!this.register[a]};r.update=function(a,b){return this.remove(a).add(a,b)}; -r.remove=function(a,b){const c=this.register[a];if(c){if(this.o)for(let d=0,e;db||c)e=e.slice(c,c+b);d&&(e=za.call(this,e));return{tag:a,result:e}}}function za(a){const b=Array(a.length);for(let c=0,d;c=this.A&&(m||!r[l])){var f=L(n,d,q),g="";switch(this.C){case "full":if(3f;h--)if(h-f>=this.A){var k=L(n,d,q,e,f);g=l.substring(f,h);M(this,r,g,k,a,c)}break}case "reverse":if(2=this.A&&M(this,r,g, +L(n,d,q,e,h),a,c);g=""}case "forward":if(1=this.A&&M(this,r,g,f,a,c);break;default:if(M(this,r,l,f,a,c),m&&1=this.A&&!g[l]){g[l]=1;const p=this.F&&l>f;M(this,t,p?f:l,L(e+(d/2>e?0:1),d,q,h-1,k-1),a,c,p?l:f)}}}}this.o||(this.register[a]=1)}return this};function L(a,b,c,d,e){return c&&1=this.A&&!c[t])if(this.s||f||this.map[t])k[r++]=t,c[t]=1;else return d;a=k;e=a.length}if(!e)return d;b||(b=100);h=this.depth&&1=d)))break;if(n){if(f)return ua(k,d,0);b[b.length]=k;return}}return!c&&k}function ua(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a} +function va(a,b,c,d){c?(d=d&&b>c,a=(a=a[d?b:c])&&a[d?c:b]):a=a[b];return a}u.contain=function(a){return!!this.register[a]};u.update=function(a,b){return this.remove(a).add(a,b)}; +u.remove=function(a,b){const c=this.register[a];if(c){if(this.o)for(let d=0,e;db||c)e=e.slice(c,c+b);d&&(e=Aa.call(this,e));return{tag:a,result:e}}}function Aa(a){const b=Array(a.length);for(let c=0,d;c=this.o&&(m||!t[k])){var f=ef;g--)if(g-f>=this.o){var l=e+d= -this.o&&Q(this,t,h,e+d=this.o&&Q(this,t,h,f,a,c);break;default:if(Q(this,t,k,f,a,c),m&&1=this.o&&!h[k]){h[k]=1;const p=this.F&&k>f;Q(this,r,p?f:k,g+e=this.o&&!c[r])if(this.s||f||this.h[r])l[t++]=r,c[r]=1;else return e;a=l;d=a.length}if(!d)return e;b||(b=100);g=this.depth&&1=e)))break;if(n){if(f)return ma(l,e,0);b[b.length]=l;return}}return!c&&l}function ma(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a} -function na(a,b,c,e){c?(e=e&&b>c,a=(a=a[e?b:c])&&a[e?c:b]):a=a[b];return a}u.contain=function(a){return!!this.register[a]};u.update=function(a,b){return this.remove(a).add(a,b)};u.remove=function(a,b){const c=this.register[a];if(c){if(this.C)for(let e=0,d;eb||c)d=d.slice(c,c+b);e&&(d=qa.call(this,d));return{tag:a,result:d}}}function qa(a){const b=Array(a.length);for(let c=0,e;c=this.o&&(m||!r[l])){var f=P(n,e,q),g="";switch(this.B){case "full":if(3f;h--)if(h-f>=this.o){var k=P(n,e,q,d,f);g=l.substring(f,h);Q(this,r,g,k,a,c)}break}case "reverse":if(2=this.o&&Q(this,r,g, +P(n,e,q,d,h),a,c);g=""}case "forward":if(1=this.o&&Q(this,r,g,f,a,c);break;default:if(Q(this,r,l,f,a,c),m&&1=this.o&&!g[l]){g[l]=1;const p=this.F&&l>f;Q(this,t,p?f:l,P(d+(e/2>d?0:1),e,q,h-1,k-1),a,c,p?l:f)}}}}this.C||(this.register[a]=1)}return this};function P(a,b,c,e,d){return c&&1=this.o&&!c[t])if(this.s||f||this.h[t])k[r++]=t,c[t]=1;else return e;a=k;d=a.length}if(!d)return e;b||(b=100);h=this.depth&&1=e)))break;if(n){if(f)return na(k,e,0);b[b.length]=k;return}}return!c&&k}function na(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a} +function oa(a,b,c,e){c?(e=e&&b>c,a=(a=a[e?b:c])&&a[e?c:b]):a=a[b];return a}u.contain=function(a){return!!this.register[a]};u.update=function(a,b){return this.remove(a).add(a,b)};u.remove=function(a,b){const c=this.register[a];if(c){if(this.C)for(let e=0,d;eb||c)d=d.slice(c,c+b);e&&(d=ra.call(this,d));return{tag:a,result:d}}}function ra(a){const b=Array(a.length);for(let c=0,e;c= this.minlength && (p || !r[l])) { - var f = d < n ? m : n / d * m | 0, g = ""; + if (l && e >= this.minlength && (n || !q[l])) { + var f = M(p, d, m), g = ""; switch(this.tokenize) { case "full": if (3 < e) { for (f = 0; f < e; f++) { for (var h = e; h > f; h--) { if (h - f >= this.minlength) { - var k = d + e < n ? m + f : n / (d + e) * (m + f) | 0; + var k = M(p, d, m, e, f); g = l.substring(f, h); - this.push_index(r, g, k, a, c); + this.push_index(q, g, k, a, c); } } } @@ -318,24 +309,24 @@ M.prototype.add = function(a, b, c, d) { case "reverse": if (2 < e) { for (h = e - 1; 0 < h; h--) { - g = l[h] + g, g.length >= this.minlength && this.push_index(r, g, d + e < n ? m + h : n / (d + e) * (m + h) | 0, a, c); + g = l[h] + g, g.length >= this.minlength && (k = M(p, d, m, e, h), this.push_index(q, g, k, a, c)); } g = ""; } case "forward": if (1 < e) { for (h = 0; h < e; h++) { - g += l[h], g.length >= this.minlength && this.push_index(r, g, f, a, c); + g += l[h], g.length >= this.minlength && this.push_index(q, g, f, a, c); } } break; default: - if (this.push_index(r, l, f, a, c), p && 1 < d && m < d - 1) { - for (e = this.resolution_ctx, g = w(), f = l, h = Math.min(p + 1, d - m), g[f] = 1, k = 1; k < h; k++) { + if (this.push_index(q, l, f, a, c), n && 1 < d && m < d - 1) { + for (e = this.resolution_ctx, g = w(), f = l, h = Math.min(n + 1, d - m), g[f] = 1, k = 1; k < h; k++) { if ((l = b[this.rtl ? d - 1 - m - k : m + k]) && l.length >= this.minlength && !g[l]) { g[l] = 1; - const q = this.bidirectional && l > f; - this.push_index(u, q ? f : l, h + d < e ? m + (k - 1) : e / (h + d) * (m + k) | 0, a, c, q ? l : f); + const u = M(e + (d / 2 > e ? 0 : 1), d, m, h - 1, k - 1), x = this.bidirectional && l > f; + this.push_index(t, x ? f : l, u, a, c, x ? l : f); } } } @@ -346,14 +337,17 @@ M.prototype.add = function(a, b, c, d) { } return this; }; -M.prototype.push_index = function(a, b, c, d, e, f) { +function M(a, b, c, d, e) { + return c && 1 < a ? b + (d || 0) <= a ? c + (e || 0) : (a - 1) / (b + (d || 0)) * (c + (e || 0)) + 1 | 0 : 0; +} +L.prototype.push_index = function(a, b, c, d, e, f) { let g = f ? this.ctx : this.map; if (!a[b] || f && !a[b][f]) { this.optimize && (g = g[c]), f ? (a = a[b] || (a[b] = w()), a[f] = 1, g = g[f] || (g[f] = w())) : a[b] = 1, g = g[b] || (g[b] = []), this.optimize || (g = g[c] || (g[c] = [])), e && -1 !== g.indexOf(d) || (g[g.length] = d, this.fastupdate && (a = this.register[d] || (this.register[d] = []), a[a.length] = g)); } }; -M.prototype.search = function(a, b, c) { - A(a) ? (c = a, a = c.query) : A(b) && (c = b); +L.prototype.search = function(a, b, c) { + z(a) ? (c = a, a = c.query) : z(b) && (c = b); let d = [], e; let f, g = 0; if (c) { @@ -365,10 +359,10 @@ M.prototype.search = function(a, b, c) { if (a && (a = this.encode(a), e = a.length, 1 < e)) { c = w(); var k = []; - for (let n = 0, r = 0, u; n < e; n++) { - if ((u = a[n]) && u.length >= this.minlength && !c[u]) { - if (this.optimize || f || this.map[u]) { - k[r++] = u, c[u] = 1; + for (let p = 0, q = 0, t; p < e; p++) { + if ((t = a[p]) && t.length >= this.minlength && !c[t]) { + if (this.optimize || f || this.map[t]) { + k[q++] = t, c[t] = 1; } else { return d; } @@ -383,13 +377,13 @@ M.prototype.search = function(a, b, c) { b || (b = 100); h = this.depth && 1 < e && !1 !== h; c = 0; - let p; - h ? (p = a[0], c = 1) : 1 < e && a.sort(aa); - for (let n, r; c < e; c++) { - r = a[c]; - h ? (n = this.add_result(d, f, b, g, 2 === e, r, p), f && !1 === n && d.length || (p = r)) : n = this.add_result(d, f, b, g, 1 === e, r); - if (n) { - return n; + let n; + h ? (n = a[0], c = 1) : 1 < e && a.sort(aa); + for (let p, q; c < e; c++) { + q = a[c]; + h ? (p = this.add_result(d, f, b, g, 2 === e, q, n), f && !1 === p && d.length || (n = q)) : p = this.add_result(d, f, b, g, 1 === e, q); + if (p) { + return p; } if (f && c === e - 1) { k = d.length; @@ -402,28 +396,28 @@ M.prototype.search = function(a, b, c) { return d; } if (1 === k) { - return pa(d[0], b, g); + return qa(d[0], b, g); } } } return ja(d, b, g, f); }; -M.prototype.add_result = function(a, b, c, d, e, f, g) { +L.prototype.add_result = function(a, b, c, d, e, f, g) { let h = [], k = g ? this.ctx : this.map; - this.optimize || (k = qa(k, f, g, this.bidirectional)); + this.optimize || (k = ra(k, f, g, this.bidirectional)); if (k) { - let p = 0; - const n = Math.min(k.length, g ? this.resolution_ctx : this.resolution); - for (let r = 0, u = 0, m, l; r < n; r++) { - if (m = k[r]) { - if (this.optimize && (m = qa(m, f, g, this.bidirectional)), d && m && e && (l = m.length, l <= d ? (d -= l, m = null) : (m = m.slice(d), d = 0)), m && (h[p++] = m, e && (u += m.length, u >= c))) { + let n = 0; + const p = Math.min(k.length, g ? this.resolution_ctx : this.resolution); + for (let q = 0, t = 0, m, l; q < p; q++) { + if (m = k[q]) { + if (this.optimize && (m = ra(m, f, g, this.bidirectional)), d && m && e && (l = m.length, l <= d ? (d -= l, m = null) : (m = m.slice(d), d = 0)), m && (h[n++] = m, e && (t += m.length, t >= c))) { break; } } } - if (p) { + if (n) { if (e) { - return pa(h, c, 0); + return qa(h, c, 0); } a[a.length] = h; return; @@ -431,21 +425,21 @@ M.prototype.add_result = function(a, b, c, d, e, f, g) { } return !b && h; }; -function pa(a, b, c) { +function qa(a, b, c) { a = 1 === a.length ? a[0] : [].concat.apply([], a); return c || a.length > b ? a.slice(c, c + b) : a; } -function qa(a, b, c, d) { +function ra(a, b, c, d) { c ? (d = d && b > c, a = (a = a[d ? b : c]) && a[d ? c : b]) : a = a[b]; return a; } -M.prototype.contain = function(a) { +L.prototype.contain = function(a) { return !!this.register[a]; }; -M.prototype.update = function(a, b) { +L.prototype.update = function(a, b) { return this.remove(a).add(a, b); }; -M.prototype.remove = function(a, b) { +L.prototype.remove = function(a, b) { const c = this.register[a]; if (c) { if (this.fastupdate) { @@ -480,8 +474,8 @@ function N(a, b, c, d, e) { } return f; } -M.prototype.searchCache = la; -M.prototype.export = function(a, b, c, d, e) { +L.prototype.searchCache = la; +L.prototype.export = function(a, b, c, d, e) { let f, g; switch(e || (e = 0)) { case 0: @@ -510,10 +504,10 @@ M.prototype.export = function(a, b, c, d, e) { default: return; } - oa(a, b || this, c ? c + "." + f : f, d, e, g); + pa(a, b || this, c ? c + "." + f : f, d, e, g); return !0; }; -M.prototype.import = function(a, b) { +L.prototype.import = function(a, b) { if (b) { switch(y(b) && (b = JSON.parse(b)), a) { case "cfg": @@ -531,8 +525,8 @@ M.prototype.import = function(a, b) { } } }; -ia(M.prototype); -function ra(a) { +ia(L.prototype); +function sa(a) { a = a.data; var b = self._index; const c = a.args; @@ -544,19 +538,19 @@ function ra(a) { b = d.encode; d.cache = !1; b && 0 === b.indexOf("function") && (d.encode = Function("return " + b)()); - a ? (Function("return " + a)()(self), self._index = new self.FlexSearch.Index(d), delete self.FlexSearch) : self._index = new M(d); + a ? (Function("return " + a)()(self), self._index = new self.FlexSearch.Index(d), delete self.FlexSearch) : self._index = new L(d); break; default: a = a.id, b = b[d].apply(b, c), postMessage("search" === d ? {id:a, msg:b} : {id:a}); } } -;let sa = 0; +;let ta = 0; function P(a) { var b; - a ? D(b = a.encode) && (a.encode = b.toString()) : a = {}; + a ? C(b = a.encode) && (a.encode = b.toString()) : a = {}; (b = (self || window)._factory) && (b = b.toString()); const c = self.exports, d = this; - this.worker = ta(b, c, a.worker); + this.worker = ua(b, c, a.worker); this.resolver = w(); if (this.worker) { if (c) { @@ -584,20 +578,20 @@ function Q(a) { const b = this, c = [].slice.call(arguments); var d = c[c.length - 1]; let e; - D(d) && (e = d, c.splice(c.length - 1, 1)); + C(d) && (e = d, c.splice(c.length - 1, 1)); d = new Promise(function(f) { setTimeout(function() { - b.resolver[++sa] = f; - b.worker.postMessage({task:a, id:sa, args:c}); + b.resolver[++ta] = f; + b.worker.postMessage({task:a, id:ta, args:c}); }); }); return e ? (d.then(e), this) : d; }; } -function ta(a, b, c) { +function ua(a, b, c) { let d; try { - d = b ? eval('new (require("worker_threads")["Worker"])("../dist/node/node.js")') : a ? new Worker(URL.createObjectURL(new Blob(["onmessage=" + ra.toString()], {type:"text/javascript"}))) : new Worker(y(c) ? c : "worker/worker.js", {type:"module"}); + d = b ? eval('new (require("worker_threads")["Worker"])("../dist/node/node.js")') : a ? new Worker(URL.createObjectURL(new Blob(["onmessage=" + sa.toString()], {type:"text/javascript"}))) : new Worker(y(c) ? c : "worker/worker.js", {type:"module"}); } catch (e) { } return d; @@ -612,12 +606,12 @@ function ta(a, b, c) { this.marker = []; this.register = w(); this.key = (c = b.key || b.id) && S(c, this.marker) || "id"; - this.fastupdate = t(a.fastupdate, !0); + this.fastupdate = r(a.fastupdate, !0); this.storetree = (c = b.store) && !0 !== c && []; this.store = c && w(); this.tag = (c = b.tag) && S(c, this.marker); this.tagindex = c && w(); - this.cache = (c = a.cache) && new L(c); + this.cache = (c = a.cache) && new K(c); a.cache = !1; this.worker = a.worker; this.async = !1; @@ -625,7 +619,7 @@ function ta(a, b, c) { let d = b.index || b.field || b; y(d) && (d = [d]); for (let e = 0, f, g; e < d.length; e++) { - f = d[e], y(f) || (g = f, f = f.field), g = A(g) ? Object.assign({}, a, g) : a, this.worker && (c[f] = new P(g), c[f].worker || (this.worker = !1)), this.worker || (c[f] = new M(g, this.register)), this.tree[e] = S(f, this.marker), this.field[e] = f; + f = d[e], y(f) || (g = f, f = f.field), g = z(g) ? Object.assign({}, a, g) : a, this.worker && (c[f] = new P(g), c[f].worker || (this.worker = !1)), this.worker || (c[f] = new L(g, this.register)), this.tree[e] = S(f, this.marker), this.field[e] = f; } if (this.storetree) { for (a = b.store, y(a) && (a = [a]), b = 0; b < a.length; b++) { @@ -695,7 +689,7 @@ function W(a, b, c, d, e, f, g, h) { } } R.prototype.add = function(a, b, c) { - A(a) && (b = a, a = T(b, this.key)); + z(a) && (b = a, a = T(b, this.key)); if (b && (a || 0 === a)) { if (this.register[a]) { return this.update(a, b); @@ -735,7 +729,7 @@ R.prototype.update = function(a, b) { return this.remove(a).add(a, b); }; R.prototype.remove = function(a) { - A(a) && (a = T(a, this.key)); + z(a) && (a = T(a, this.key)); if (this.register[a]) { var b = this.fastupdate && !this.worker; for (var c = 0; c < this.field.length && (this.index[this.field[c]].remove(a, b), !b); c++) { @@ -751,55 +745,55 @@ R.prototype.remove = function(a) { return this; }; R.prototype.search = function(a, b, c, d) { - A(a) ? (c = a, a = c.query) : A(b) && (c = b, b = 0); - let e = [], f = [], g, h, k, p, n, r, u = 0; + z(a) ? (c = a, a = c.query) : z(b) && (c = b, b = 0); + let e = [], f = [], g, h, k, n, p, q, t = 0; if (c) { if (c.constructor === Array) { k = c, c = null; } else { k = (g = c.pluck) || c.index || c.field || c; - p = c.tag; + n = c.tag; h = this.store && c.enrich; - n = "and" === c.bool; + p = "and" === c.bool; b = c.limit || 100; - r = c.offset || 0; - if (p && (y(p) && (p = [p]), !a)) { - for (let l = 0, q; l < p.length; l++) { - if (q = ua.call(this, p[l], b, r, h)) { - e[e.length] = q, u++; + q = c.offset || 0; + if (n && (y(n) && (n = [n]), !a)) { + for (let l = 0, u; l < n.length; l++) { + if (u = va.call(this, n[l], b, q, h)) { + e[e.length] = u, t++; } } - return u ? e : []; + return t ? e : []; } y(k) ? k = [k] : k.constructor === Array || (k = null); } } k || (k = this.field); - n = n && (1 < k.length || p && 1 < p.length); + p = p && (1 < k.length || n && 1 < n.length); const m = !d && (this.worker || this.async) && []; - for (let l = 0, q, x, z; l < k.length; l++) { + for (let l = 0, u, x, A; l < k.length; l++) { let B; x = k[l]; y(x) || (B = x, x = x.field); if (m) { m[l] = this.index[x].searchAsync(a, b, B || c); } else { - z = (q = d ? d[l] : this.index[x].search(a, b, B || c)) && q.length; - if (p && z) { - const C = []; - let G = 0; - n && (C[0] = [q]); - for (let V = 0, ma, O; V < p.length; V++) { - if (ma = p[V], z = (O = this.tagindex[ma]) && O.length) { - G++, C[C.length] = n ? [O] : O; + A = (u = d ? d[l] : this.index[x].search(a, b, B || c)) && u.length; + if (n && A) { + const D = []; + let ma = 0; + p && (D[0] = [u]); + for (let V = 0, na, O; V < n.length; V++) { + if (na = n[V], A = (O = this.tagindex[na]) && O.length) { + ma++, D[D.length] = p ? [O] : O; } } - G && (q = n ? ja(C, b || 100, r || 0) : ka(q, C), z = q.length); + ma && (u = p ? ja(D, b || 100, q || 0) : ka(u, D), A = u.length); } - if (z) { - f[u] = x, e[u++] = q; + if (A) { + f[t] = x, e[t++] = u; } else { - if (n) { + if (p) { return []; } } @@ -807,39 +801,39 @@ R.prototype.search = function(a, b, c, d) { } if (m) { const l = this; - return new Promise(function(q) { + return new Promise(function(u) { Promise.all(m).then(function(x) { - q(l.search(a, b, c, x)); + u(l.search(a, b, c, x)); }); }); } - if (!u) { + if (!t) { return []; } if (g && (!h || !this.store)) { return e[0]; } - for (let l = 0, q; l < f.length; l++) { - q = e[l]; - q.length && h && (q = va.call(this, q)); + for (let l = 0, u; l < f.length; l++) { + u = e[l]; + u.length && h && (u = wa.call(this, u)); if (g) { - return q; + return u; } - e[l] = {field:f[l], result:q}; + e[l] = {field:f[l], result:u}; } return e; }; -function ua(a, b, c, d) { +function va(a, b, c, d) { let e = this.tagindex[a], f = e && e.length - c; if (f && 0 < f) { if (f > b || c) { e = e.slice(c, c + b); } - d && (e = va.call(this, e)); + d && (e = wa.call(this, e)); return {tag:a, result:e}; } } -function va(a) { +function wa(a) { const b = Array(a.length); for (let c = 0, d; c < a.length; c++) { d = a[c], b[c] = {key:d, doc:this.store[d]}; @@ -880,7 +874,7 @@ R.prototype.export = function(a, b, c, d, e) { default: return; } - oa(a, this, c, d, e, f); + pa(a, this, c, d, e, f); } }; R.prototype.import = function(a, b) { @@ -908,26 +902,26 @@ R.prototype.import = function(a, b) { } }; ia(R.prototype); -var xa = {encode:wa, rtl:!1, tokenize:""}; -const ya = /[\W_]+/, za = F("[\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5]"), Aa = F("[\u00e8\u00e9\u00ea\u00eb]"), Ba = F("[\u00ec\u00ed\u00ee\u00ef]"), Ca = F("[\u00f2\u00f3\u00f4\u00f5\u00f6\u0151]"), Da = F("[\u00f9\u00fa\u00fb\u00fc\u0171]"), Ea = F("[\u00fd\u0177\u00ff]"), Fa = F("\u00f1"), Ga = F("[\u00e7c]"), Ha = F("\u00df"), Ia = F(" & "), Ja = [za, "a", Aa, "e", Ba, "i", Ca, "o", Da, "u", Ea, "y", Fa, "n", Ga, "k", Ha, "s", Ia, " and "]; -function wa(a) { - return this.pipeline(E(a).toLowerCase(), !a.normalize && Ja, ya, !1); +var ya = {encode:xa, rtl:!1, tokenize:""}; +const za = /[\W_]+/, Aa = F("[\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5]"), Ba = F("[\u00e8\u00e9\u00ea\u00eb]"), Ca = F("[\u00ec\u00ed\u00ee\u00ef]"), Da = F("[\u00f2\u00f3\u00f4\u00f5\u00f6\u0151]"), Ea = F("[\u00f9\u00fa\u00fb\u00fc\u0171]"), Fa = F("[\u00fd\u0177\u00ff]"), Ga = F("\u00f1"), Ha = F("[\u00e7c]"), Ia = F("\u00df"), Ja = F(" & "), Ka = [Aa, "a", Ba, "e", Ca, "i", Da, "o", Ea, "u", Fa, "y", Ga, "n", Ha, "k", Ia, "s", Ja, " and "]; +function xa(a) { + return this.pipeline(E(a).toLowerCase(), !a.normalize && Ka, za, !1); } -;var La = {encode:Ka, rtl:!1, tokenize:"strict"}; -const Ma = /[^a-z0-9]+/, Na = {b:"p", v:"f", w:"f", z:"s", x:"s", "\u00df":"s", d:"t", n:"m", c:"k", g:"k", j:"k", q:"k", i:"e", y:"e", u:"o"}; -function Ka(a) { - a = wa.call(this, a).join(" "); +;var Ma = {encode:La, rtl:!1, tokenize:"strict"}; +const Na = /[^a-z0-9]+/, Oa = {b:"p", v:"f", w:"f", z:"s", x:"s", "\u00df":"s", d:"t", n:"m", c:"k", g:"k", j:"k", q:"k", i:"e", y:"e", u:"o"}; +function La(a) { + a = xa.call(this, a).join(" "); const b = []; if (a) { - const c = a.split(Ma), d = c.length; + const c = a.split(Na), d = c.length; for (let e = 0, f, g = 0; e < d; e++) { if ((a = c[e]) && (!this.filter || !this.filter[a])) { f = a[0]; - let h = Na[f] || f, k = h; - for (let p = 1; p < a.length; p++) { - f = a[p]; - const n = Na[f] || f; - n && n !== k && (h += n, k = n); + let h = Oa[f] || f, k = h; + for (let n = 1; n < a.length; n++) { + f = a[n]; + const p = Oa[f] || f; + p && p !== k && (h += p, k = p); } b[g++] = h; } @@ -935,27 +929,27 @@ function Ka(a) { } return b; } -;var Pa = {encode:Oa, rtl:!1, tokenize:""}; -const Qa = F("ae"), Ra = F("oe"), Sa = F("sh"), Ta = F("th"), Ua = F("ph"), Va = F("pf"), Wa = [Qa, "a", Ra, "o", Sa, "s", Ta, "t", Ua, "f", Va, "f", ]; -function Oa(a, b) { - a && (a = Ka.call(this, a).join(" "), 2 < a.length && (a = H(a, Wa)), b || (1 < a.length && (a = I(a)), a && (a = a.split(" ")))); +;var Qa = {encode:Pa, rtl:!1, tokenize:""}; +const Ra = F("ae"), Sa = F("oe"), Ta = F("sh"), Ua = F("th"), Va = F("ph"), Wa = F("pf"), Xa = [Ra, "a", Sa, "o", Ta, "s", Ua, "t", Va, "f", Wa, "f", ]; +function Pa(a, b) { + a && (a = La.call(this, a).join(" "), 2 < a.length && (a = G(a, Xa)), b || (1 < a.length && (a = H(a)), a && (a = a.split(" ")))); return a; } -;var Ya = {encode:Xa, rtl:!1, tokenize:""}; -const Za = F("(?!\\b)[aeiouy]"); -function Xa(a) { - a && (a = Oa.call(this, a, !0), 1 < a.length && (a = a.replace(Za, "")), 1 < a.length && (a = I(a)), a && (a = a.split(" "))); +;var Za = {encode:Ya, rtl:!1, tokenize:""}; +const $a = F("(?!\\b)[aeiouy]"); +function Ya(a) { + a && (a = Pa.call(this, a, !0), 1 < a.length && (a = a.replace($a, "")), 1 < a.length && (a = H(a)), a && (a = a.split(" "))); return a; } -;J["latin:default"] = ea; -J["latin:simple"] = xa; -J["latin:balance"] = La; -J["latin:advanced"] = Pa; -J["latin:extra"] = Ya; +;I["latin:default"] = ea; +I["latin:simple"] = ya; +I["latin:balance"] = Ma; +I["latin:advanced"] = Qa; +I["latin:extra"] = Za; const X = self; let Y; -const Z = {Index:M, Document:R, Worker:P, registerCharset:function(a, b) { - J[a] = b; +const Z = {Index:L, Document:R, Worker:P, registerCharset:function(a, b) { + I[a] = b; }, registerLanguage:function(a, b) { ha[a] = b; }}; diff --git a/dist/flexsearch.es5.js b/dist/flexsearch.es5.js index 356fb1f..eebdf60 100644 --- a/dist/flexsearch.es5.js +++ b/dist/flexsearch.es5.js @@ -6,40 +6,40 @@ * https://github.com/nextapps-de/flexsearch */ (function(self){'use strict';var u;function aa(a){var b=0;return function(){return b>>0)+"_",f=0;return b}); -x("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c>>0)+"_",f=0;return b}); +y("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c=this.D&&(f||!e[l])){var p=dp;q--)if(q-p>=this.D){var r=d+m=this.D&&P(this, -e,n,d+m=this.D&&P(this,e,n,p,a,c);break;default:if(P(this,e,l,p,a,c),f&&1=this.D&&!n[l]){n[l]=1;var t=this.J&&l>p;P(this,h,t?p:l,q+d=this.D&&!c[p])if(this.B||e||this.map[p])k[m++]=p,c[p]=1;else return d;a=k;h=a.length}}if(!h)return d;b||(b=100);g=this.depth&&1=this.D&&(f||!e[l])){var p=O(g,d,k),m="";switch(this.G){case "full":if(3p;q--)if(q-p>=this.D){var r=O(g,d,k,n,p);m=l.substring(p,q);P(this,e,m,r,a,c)}break}case "reverse":if(2=this.D&&P(this,e,m,O(g,d,k,n, +q),a,c);m=""}case "forward":if(1=this.D&&P(this,e,m,p,a,c);break;default:if(P(this,e,l,p,a,c),f&&1=this.D&&!m[l]){m[l]=1;var t=this.J&&l>p;P(this,h,t?p:l,O(n+(d/2>n?0:1),d,k,q-1,r-1),a,c,t?l:p)}}}}this.s||(this.register[a]=1)}return this};function O(a,b,c,d,f){return c&&1=this.D&&!c[p])if(this.B||e||this.map[p])k[n++]=p,c[p]=1;else return d;a=k;h=a.length}}if(!h)return d;b||(b=100);g=this.depth&&1=d)))break;if(m){if(g)return za(k,d,0);b[b.length]=k;return}}return!c&&k}function za(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a} +function ya(a,b,c,d,f,g,e,h){var k=[],l=h?a.h:a.map;a.B||(l=Aa(l,e,h,a.J));if(l){for(var n=0,p=Math.min(l.length,h?a.l:a.H),m=0,q=0,r,t;m=d)))break;if(n){if(g)return za(k,d,0);b[b.length]=k;return}}return!c&&k}function za(a,b,c){a=1===a.length?a[0]:[].concat.apply([],a);return c||a.length>b?a.slice(c,c+b):a} function Aa(a,b,c,d){c?(d=d&&b>c,a=(a=a[d?b:c])&&a[d?c:b]):a=a[b];return a}u.contain=function(a){return!!this.register[a]};u.update=function(a,b){return this.remove(a).add(a,b)}; u.remove=function(a,b){var c=this.register[a];if(c){if(this.s)for(var d=0,f;db||c)f=f.slice(c,c+b);d&&(f=Fa.call(this,f));return{tag:a,result:f}}}function Fa(a){for(var b=Array(a.length),c=0,d;cb||c)f=f.slice(c,c+b);d&&(f=Fa.call(this,f));return{tag:a,result:f}}}function Fa(a){for(var b=Array(a.length),c=0,d;c=this.h&&(p||!q[k])){var h=dh;f--)if(f-h>=this.h){var l=d+e= -this.h&&L(this,q,g,d+e=this.h&&L(this,q,g,h,a,b);break;default:if(L(this,q,k,h,a,b),p&&1=this.h&&!g[k]){g[k]=1;const t=this.l&&k>h;L(this,r,t?h:k,f+d=this.h&&!b[r])if(this.g||h||this.i[r])l[q++]=r,b[r]=1;else return d;a=l;e=a.length}if(!e)return d;c||(c=100);f=this.j&&1=d)))break;if(m){if(h)return O(l,d,0);c[c.length]=l;return}}return!b&&l}function O(a,c,b){a=1===a.length?a[0]:[].concat.apply([],a);return b||a.length>c?a.slice(b,b+c):a} -function P(a,c,b,d){b?(d=d&&c>b,a=(a=a[d?c:b])&&a[d?b:c]):a=a[c];return a}K.prototype.contain=function(a){return!!this.register[a]};K.prototype.update=function(a,c){return this.remove(a).add(a,c)};K.prototype.remove=function(a,c){const b=this.register[a];if(b){if(this.s)for(let d=0,e;d=this.h&&(n||!q[l])){var h=K(p,d,m),f="";switch(this.C){case "full":if(3h;g--)if(g-h>=this.h){var k=K(p,d,m,e,h);f=l.substring(h,g);L(this,q,f,k,a,b)}break}case "reverse":if(2=this.h&&L(this, +q,f,K(p,d,m,e,g),a,b);f=""}case "forward":if(1=this.h&&L(this,q,f,h,a,b);break;default:if(L(this,q,l,h,a,b),n&&1=this.h&&!f[l]){f[l]=1;const u=this.l&&l>h;L(this,r,u?h:l,K(e+(d/2>e?0:1),d,m,g-1,k-1),a,b,u?l:h)}}}}this.s||(this.register[a]=1)}return this};function K(a,c,b,d,e){return b&&1=this.h&&!b[r])if(this.g||h||this.i[r])k[q++]=r,b[r]=1;else return d;a=k;e=a.length}if(!e)return d;c||(c=100);g=this.j&&1=d)))break;if(p){if(h)return O(k,d,0);c[c.length]=k;return}}return!b&&k}function O(a,c,b){a=1===a.length?a[0]:[].concat.apply([],a);return b||a.length>c?a.slice(b,b+c):a} +function P(a,c,b,d){b?(d=d&&c>b,a=(a=a[d?c:b])&&a[d?b:c]):a=a[c];return a}J.prototype.contain=function(a){return!!this.register[a]};J.prototype.update=function(a,c){return this.remove(a).add(a,c)};J.prototype.remove=function(a,c){const b=this.register[a];if(b){if(this.s)for(let d=0,e;d= this.minlength) && (depth || !dupes[term])){ - const score = length < resolution ? i : (resolution / length * i) | 0; + const score = get_score(resolution, length, i); let token = ""; switch(this.tokenize){ @@ -169,14 +168,7 @@ Index.prototype.add = function(id, content, _append, _skip_update){ if((y - x) >= this.minlength){ - const partial_score = (length + term_length) < resolution ? i + x : (resolution / (length + term_length) * (i + x)) | 0; - - // console.log("resolution", resolution); - // console.log("length", length); - // console.log("term_length", term_length); - // console.log("i", i); - // console.log((length + term_length) < resolution ? i + x : resolution / (length + term_length) * (i + x)); - + const partial_score = get_score(resolution, length, i, term_length, x); token = term.substring(x, y); this.push_index(dupes, token, partial_score, id, _append); } @@ -186,7 +178,7 @@ Index.prototype.add = function(id, content, _append, _skip_update){ break; } - // fallthrough to next case when term length < 4 + // fallthrough to next case when term length < 4 case "reverse": @@ -200,15 +192,7 @@ Index.prototype.add = function(id, content, _append, _skip_update){ if(token.length >= this.minlength){ - const partial_score = (length + term_length) < resolution ? i + x : (resolution / (length + term_length) * (i + x)) | 0; - - // console.log("token", token); - // console.log("resolution", resolution); - // console.log("length", length); - // console.log("term_length", term_length); - // console.log("i", i); - // console.log((length + term_length) < resolution ? i + x : (resolution / (length + term_length) * (i + x))); - + const partial_score = get_score(resolution, length, i, term_length, x); this.push_index(dupes, token, partial_score, id, _append); } } @@ -216,7 +200,7 @@ Index.prototype.add = function(id, content, _append, _skip_update){ token = ""; } - // fallthrough to next case to apply forward also + // fallthrough to next case to apply forward also case "forward": @@ -228,13 +212,6 @@ Index.prototype.add = function(id, content, _append, _skip_update){ if(token.length >= this.minlength){ - // console.log("token", token); - // console.log("resolution", resolution); - // console.log("length", length); - // console.log("term_length", term_length); - // console.log("i", i); - // console.log(score); - this.push_index(dupes, token, score, id, _append); } } @@ -245,12 +222,6 @@ Index.prototype.add = function(id, content, _append, _skip_update){ //case "strict": default: - // console.log("term", term); - // console.log("resolution", resolution); - // console.log("length", length); - // console.log("i", i); - // console.log(score); - this.push_index(dupes, term, score, id, _append); if(depth){ @@ -273,16 +244,7 @@ Index.prototype.add = function(id, content, _append, _skip_update){ dupes_inner[term] = 1; - const context_score = (size + length) < resolution ? i + (x - 1) : ((resolution / (size + length) * (i + x)) | 0); - - // console.log("term", term); - // console.log("resolution", resolution); - // console.log("size", size); - // console.log("length", length); - // console.log("i", i); - // console.log("x", x); - // console.log(resolution / (size + length) * (i + x)); - + const context_score = get_score(resolution + ((length / 2) > resolution ? 0 : 1), length, i, size - 1, x - 1); const swap = this.bidirectional && (term > keyword); this.push_index(dupes_ctx, swap ? keyword : term, context_score, id, _append, swap ? term : keyword); } @@ -300,6 +262,46 @@ Index.prototype.add = function(id, content, _append, _skip_update){ return this; }; +/** + * @param {number} resolution + * @param {number} length + * @param {number} i + * @param {number=} term_length + * @param {number=} x + * @returns {number} + */ + +function get_score(resolution, length, i, term_length, x){ + + // console.log("resolution", resolution); + // console.log("length", length); + // console.log("term_length", term_length); + // console.log("i", i); + // console.log("x", x); + // console.log((resolution - 1) / (length + (term_length || 0)) * (i + (x || 0)) + 1); + + // the first resolution slot is reserved for the best match, + // when a query matches the first word(s). + + // also to stretch score to the whole range of resolution, the + // calculation is shift by one and cut the floating point. + // this needs the resolution "1" to be handled additionally. + + // do not stretch the resolution more than the term length will + // improve performance and memory, also it improves scoring in + // most cases between a short document and a long document + + return i && (resolution > 1) ? ( + + (length + (term_length || 0)) <= resolution ? + + i + (x || 0) + : + ((resolution - 1) / (length + (term_length || 0)) * (i + (x || 0)) + 1) | 0 + ): + 0; +} + /** * @private * @param dupes @@ -404,7 +406,7 @@ Index.prototype.search = function(query, limit, options){ if(term && (term.length >= this.minlength) && !dupes[term]){ - // the fast path just could applied when not in memory-optimized mode + // this fast path just could applied when not in memory-optimized mode if(!this.optimize && !suggest && !this.map[term]){ @@ -452,10 +454,17 @@ Index.prototype.search = function(query, limit, options){ term = query[index]; + // console.log(keyword); + // console.log(term); + // console.log(""); + if(depth){ arr = this.add_result(result, suggest, limit, offset, length === 2, term, keyword); + // console.log(arr); + // console.log(result); + // when suggestion enabled just forward keyword if term was found // as long as the result is empty forward the pointer also diff --git a/src/intersect.js b/src/intersect.js index be42824..0762987 100644 --- a/src/intersect.js +++ b/src/intersect.js @@ -1,7 +1,203 @@ import { create_object, concat } from "./common.js"; /** - * Implementation based on Array.indexOf() + * Implementation based on Array.indexOf() provides better performance, + * but it needs at least one word in the query which is less frequent. + * Also on large indexes it does not scale well performance-wise. + * This strategy also lacks of suggestion capabilities (matching & sorting). + * + * @param arrays + * @param limit + * @param offset + * @param {boolean|Array=} suggest + * @returns {Array} + */ + +// export function intersect(arrays, limit, offset, suggest) { +// +// const length = arrays.length; +// let result = []; +// let check; +// +// // determine shortest array and collect results +// // from the sparse relevance arrays +// +// let smallest_size; +// let smallest_arr; +// let smallest_index; +// +// for(let x = 0; x < length; x++){ +// +// const arr = arrays[x]; +// const len = arr.length; +// +// let size = 0; +// +// for(let y = 0, tmp; y < len; y++){ +// +// tmp = arr[y]; +// +// if(tmp){ +// +// size += tmp.length; +// } +// } +// +// if(!smallest_size || (size < smallest_size)){ +// +// smallest_size = size; +// smallest_arr = arr; +// smallest_index = x; +// } +// } +// +// smallest_arr = smallest_arr.length === 1 ? +// +// smallest_arr[0] +// : +// concat(smallest_arr); +// +// if(suggest){ +// +// suggest = [smallest_arr]; +// check = create_object(); +// } +// +// let size = 0; +// let steps = 0; +// +// // process terms in reversed order often results in better performance. +// // the outer loop must be the words array, using the +// // smallest array here disables the "fast fail" optimization. +// +// for(let x = length - 1; x >= 0; x--){ +// +// if(x !== smallest_index){ +// +// steps++; +// +// const word_arr = arrays[x]; +// const word_arr_len = word_arr.length; +// const new_arr = []; +// +// let count = 0; +// +// for(let z = 0, id; z < smallest_arr.length; z++){ +// +// id = smallest_arr[z]; +// +// let found; +// +// // process relevance in forward order (direction is +// // important for adding IDs during the last round) +// +// for(let y = 0; y < word_arr_len; y++){ +// +// const arr = word_arr[y]; +// +// if(arr.length){ +// +// found = arr.indexOf(id) !== -1; +// +// if(found){ +// +// // check if in last round +// +// if(steps === length - 1){ +// +// if(offset){ +// +// offset--; +// } +// else{ +// +// result[size++] = id; +// +// if(size === limit){ +// +// // fast path "end reached" +// +// return result; +// } +// } +// +// if(suggest){ +// +// check[id] = 1; +// } +// } +// +// break; +// } +// } +// } +// +// if(found){ +// +// new_arr[count++] = id; +// } +// } +// +// if(suggest){ +// +// suggest[steps] = new_arr; +// } +// else if(!count){ +// +// return []; +// } +// +// smallest_arr = new_arr; +// } +// } +// +// if(suggest){ +// +// // needs to iterate in reverse direction +// +// for(let x = suggest.length - 1, arr, len; x >= 0; x--){ +// +// arr = suggest[x]; +// len = arr && arr.length; +// +// if(len){ +// +// for(let y = 0, id; y < len; y++){ +// +// id = arr[y]; +// +// if(!check[id]){ +// +// check[id] = 1; +// +// if(offset){ +// +// offset--; +// } +// else{ +// +// result[size++] = id; +// +// if(size === limit){ +// +// // fast path "end reached" +// +// return result; +// } +// } +// } +// } +// } +// } +// } +// +// return result; +// } + +/** + * Implementation based on Object[key] provides better suggestions + * capabilities and has less performance scaling issues on large indexes. + * * @param arrays * @param limit * @param offset @@ -14,94 +210,48 @@ export function intersect(arrays, limit, offset, suggest) { const length = arrays.length; let result = []; let check; - - // determine shortest array and collect results - // from the sparse relevance arrays - - let smallest_size; - let smallest_arr; - let smallest_index; - - for(let x = 0; x < length; x++){ - - const arr = arrays[x]; - const len = arr.length; - - let size = 0; - - for(let y = 0, tmp; y < len; y++){ - - tmp = arr[y]; - - if(tmp){ - - size += tmp.length; - } - } - - if(!smallest_size || (size < smallest_size)){ - - smallest_size = size; - smallest_arr = arr; - smallest_index = x; - } - } - - smallest_arr = smallest_arr.length === 1 ? - - smallest_arr[0] - : - concat(smallest_arr); + let check_suggest; + let size = 0; if(suggest){ - suggest = [smallest_arr]; - check = create_object(); + suggest = []; } - let size = 0; - let steps = 0; - - // TODO: the first word should be processed in the last round? - - // process terms in reversed order often results in better performance - // the outer loop must be the words array, - // using the smallest array here disables the "fast fail" optimization + // process terms in reversed order often has advantage for the fast path "end reached". + // also a reversed order prioritize the order of words from a query. for(let x = length - 1; x >= 0; x--){ - if(x !== smallest_index){ + const word_arr = arrays[x]; + const word_arr_len = word_arr.length; + const check_new = create_object(); - steps++; + let found = !check; - const word_arr = arrays[x]; - const word_arr_len = word_arr.length; - const new_arr = []; + // process relevance in forward order (direction is + // important for adding IDs during the last round) - let count = 0; + for(let y = 0; y < word_arr_len; y++){ - for(let z = 0, id; z < smallest_arr.length; z++){ + const arr = word_arr[y]; + const arr_len = arr.length; - id = smallest_arr[z]; + if(arr_len){ - let found; + // loop through IDs - // process relevance in forward order (direction is - // important for the "fill" during the last round) + for(let z = 0, check_idx, id; z < arr_len; z++){ - for(let y = 0; y < word_arr_len; y++){ + id = arr[z]; - const arr = word_arr[y]; + if(check){ - if(arr.length){ - - found = arr.indexOf(id) !== -1; - - if(found){ + if(check[id]){ // check if in last round - if(steps === length - 1){ + if(!x){ if(offset){ @@ -118,47 +268,63 @@ export function intersect(arrays, limit, offset, suggest) { return result; } } - - if(suggest){ - - check[id] = 1; - } } - break; + if(x || suggest){ + + check_new[id] = 1; + } + + found = true; + } + + if(suggest){ + + check_suggest[id] = (check_idx = check_suggest[id]) ? check_idx++ : check_idx = 1; + + // do not adding IDs which are already included in the result (saves one loop) + + if(check_idx < word_arr_len){ + + const tmp = suggest[check_idx - 1] || (suggest[check_idx - 1] = []); + tmp[tmp.length] = id; + } } } - } + else{ - if(found){ + // pre-fill in first round - new_arr[count++] = id; + check_new[id] = 1; + } } } - - if(suggest){ - - suggest[steps] = new_arr; - } - else if(!count){ - - return []; - } - - smallest_arr = new_arr; } + + if(suggest){ + + // re-use the first pre-filled check for suggestions + + check || (check_suggest = check_new); + } + else if(!found){ + + return []; + } + + check = check_new; } if(suggest){ - // has to iterate in reverse direction + // needs to iterate in reverse direction for(let x = suggest.length - 1, arr, len; x >= 0; x--){ arr = suggest[x]; - len = arr && arr.length; + len = /*arr &&*/ arr.length; - if(len){ + //if(len){ for(let y = 0, id; y < len; y++){ @@ -166,8 +332,6 @@ export function intersect(arrays, limit, offset, suggest) { if(!check[id]){ - check[id] = 1; - if(offset){ offset--; @@ -183,154 +347,17 @@ export function intersect(arrays, limit, offset, suggest) { return result; } } + + check[id] = 1; } } - } + //} } } return result; } -/** - * Implementation based on Object[key] - * @param arrays - * @param limit - * @param offset - * @param {boolean|Array=} suggest - * @returns {Array} - */ - -// export function intersect(arrays, limit, offset, suggest) { -// -// const length = arrays.length; -// let result = []; -// -// // arrays.sort(function(a, b){ -// // -// // return a.length - b.length; -// // }); -// -// let check; -// let count = 0; -// -// if(suggest){ -// -// suggest = []; -// } -// -// // terms in reversed order! -// for(let x = length - 1; x >= 0; x--){ -// -// const word_arr = arrays[x]; -// const word_arr_len = word_arr.length; -// const new_check = create_object(); -// -// let found = !check; -// -// // relevance in forward order -// for(let y = 0, count_suggest = 0; y < word_arr_len; y++){ -// -// //const arr = [].concat.apply([], word_arr); -// const arr = word_arr[y]; -// const arr_len = arr.length; -// -// if(arr_len){ -// -// // ids -// for(let z = 0, id; z < arr_len; z++){ -// -// id = arr[z]; -// -// if(!check){ -// -// new_check[id] = 1; -// } -// else if(check[id]){ -// -// if(!x){ -// -// if(offset){ -// -// offset--; -// } -// else{ -// -// result[count++] = id; -// -// if(count === limit){ -// -// // fast path "end reached" -// -// return result; -// } -// } -// } -// else{ -// -// if(suggest && (count_suggest < limit)){ -// -// const tmp = suggest[y] || (suggest[y] = []); -// tmp[tmp.length] = id; -// count_suggest++; -// } -// -// new_check[id] = 1; -// } -// -// found = true; -// } -// } -// } -// } -// -// if(!found && !suggest){ -// -// return []; -// } -// -// check = new_check; -// } -// -// if(suggest){ -// -// for(let i = suggest.length - 1, res, len; i >= 0; i--){ -// -// res = suggest[i]; -// len = res && res.length; -// -// if(len && offset){ -// -// if(len <= offset){ -// -// offset -= len; -// len = 0; -// } -// else{ -// -// len -= offset; -// } -// } -// -// if(len){ -// -// if(count + len >= limit){ -// -// return result.concat(res.slice(offset, limit - count + offset)); -// } -// else{ -// -// result = result.concat(offset ? res.slice(offset) : res); -// count += len; -// offset = 0; -// } -// } -// } -// } -// -// return result; -// } - /** * @param mandatory * @param arrays