mirror of
https://github.com/ONLYOFFICE/sdkjs.git
synced 2026-02-10 18:15:19 +08:00
[SE] refactor cache for exact mathces
This commit is contained in:
@ -2903,6 +2903,174 @@ function (window, undefined) {
|
||||
* @typedef {cNumber | cString | cBool | cError} LookUpElement
|
||||
*/
|
||||
|
||||
function TypedMapCache() {
|
||||
this.data = {};
|
||||
}
|
||||
|
||||
TypedMapCache.prototype.getData = function (ws, rowCol, type, startIndex, endIndex, bHor) {
|
||||
const wsId = ws.getId();
|
||||
if (!this.data[wsId]) {
|
||||
this.data[wsId] = {vertical: {}, horizontal: {}};
|
||||
}
|
||||
const axisData = bHor ? this.data[wsId].horizontal : this.data[wsId].vertical;
|
||||
if (!axisData[rowCol]) {
|
||||
axisData[rowCol] = {start: startIndex, end: endIndex, data: {}};
|
||||
const c1 = bHor ? startIndex : rowCol;
|
||||
const r1 = bHor ? rowCol : startIndex;
|
||||
const c2 = bHor ? endIndex : rowCol;
|
||||
const r2 = bHor ? rowCol : endIndex;
|
||||
const fullRange = ws.getRange3(r1, c1, r2, c2);
|
||||
fullRange._foreachNoEmpty(function (cell, r, c) {
|
||||
const value = checkTypeCell(cell, true);
|
||||
const index = bHor ? c : r;
|
||||
if (!axisData[rowCol].data[value.type]) {
|
||||
axisData[rowCol].data[value.type] = new Map();
|
||||
}
|
||||
const map = axisData[rowCol].data[value.type];
|
||||
if (!map.has(value.value)) {
|
||||
map.set(value.value, []);
|
||||
}
|
||||
const arr = axisData[rowCol].data[value.type].get(value.value);
|
||||
arr.push(index);
|
||||
});
|
||||
axisData[rowCol].start = startIndex;
|
||||
axisData[rowCol].end = endIndex;
|
||||
} else {
|
||||
if (startIndex < axisData[rowCol].start) {
|
||||
const c1 = bHor ? startIndex : rowCol;
|
||||
const r1 = bHor ? rowCol : startIndex;
|
||||
const c2 = bHor ? axisData[rowCol].start : rowCol;
|
||||
const r2 = bHor ? rowCol : axisData[rowCol].start;
|
||||
const fullRange = ws.getRange3(r1, c1, r2, c2);
|
||||
fullRange._foreachNoEmpty(function (cell, r, c) {
|
||||
const value = checkTypeCell(cell, true);
|
||||
const index = bHor ? c : r;
|
||||
if (!axisData[rowCol].data[value.type]) {
|
||||
axisData[rowCol].data[value.type] = new Map();
|
||||
}
|
||||
const map = axisData[rowCol].data[value.type];
|
||||
if (!map.has(value.value)) {
|
||||
map.set(value.value, []);
|
||||
}
|
||||
const arr = axisData[rowCol].data[value.type].get(value.value);
|
||||
arr.unshift(index);
|
||||
});
|
||||
axisData[rowCol].start = startIndex;
|
||||
}
|
||||
if (endIndex > axisData[rowCol].end) {
|
||||
const c1 = bHor ? axisData[rowCol].end : rowCol;
|
||||
const r1 = bHor ? rowCol : axisData[rowCol].end;
|
||||
const c2 = bHor ? endIndex : rowCol;
|
||||
const r2 = bHor ? rowCol : endIndex;
|
||||
const fullRange = ws.getRange3(r1, c1, r2, c2);
|
||||
fullRange._foreachNoEmpty(function (cell, r, c) {
|
||||
const value = checkTypeCell(cell, true);
|
||||
const index = bHor ? c : r;
|
||||
if (!axisData[rowCol].data[value.type]) {
|
||||
axisData[rowCol].data[value.type] = new Map();
|
||||
}
|
||||
const map = axisData[rowCol].data[value.type];
|
||||
if (!map.has(value.value)) {
|
||||
map.set(value.value, []);
|
||||
}
|
||||
const arr = axisData[rowCol].data[value.type].get(value.value);
|
||||
arr.push(index);
|
||||
});
|
||||
axisData[rowCol].end = endIndex;
|
||||
}
|
||||
}
|
||||
return axisData[rowCol].data[type];
|
||||
};
|
||||
TypedMapCache.prototype.changeAxisData = function (cellRowOrCol, axisData, oldValue, oldType, newValue, newType, bHor) {
|
||||
const staticIndex = bHor ? cellRowOrCol.nRow : cellRowOrCol.nCol;
|
||||
const changedIndex = bHor ? cellRowOrCol.nCol : cellRowOrCol.nRow;
|
||||
const colRowData = axisData[staticIndex];
|
||||
if (colRowData && changedIndex >= colRowData.start && changedIndex <= colRowData.end) {
|
||||
if (oldValue !== null) {
|
||||
const mapOldType = colRowData.data[oldType];
|
||||
if (mapOldType) {
|
||||
if (mapOldType.has(oldValue)) {
|
||||
const arr = mapOldType.get(oldValue);
|
||||
if (arr.length === 1) {
|
||||
mapOldType.delete(oldValue);
|
||||
} else {
|
||||
const newArr = [];
|
||||
for (let i = 0; i < arr.length; i += 1) {
|
||||
if (arr[i] !== changedIndex) {
|
||||
newArr.push(arr[i]);
|
||||
}
|
||||
}
|
||||
mapOldType.set(newArr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newValue !== null) {
|
||||
const mapNewType = colRowData.data[newType];
|
||||
if (mapNewType) {
|
||||
if (mapNewType.has(newValue)) {
|
||||
const arr = mapNewType.get(newValue);
|
||||
const newArr = [];
|
||||
if (arr.length === 1) {
|
||||
newArr.push(arr[0]);
|
||||
changedIndex > arr[0] ? newArr.push(changedIndex) : newArr.unshift(changedIndex);
|
||||
} else {
|
||||
if (arr[0] < changedIndex) {
|
||||
newArr.push(changedIndex);
|
||||
}
|
||||
for(let i = 1; i < arr.length; i += 1) {
|
||||
if (arr[i] < changedIndex && arr[i - 1] > changedIndex) {
|
||||
newArr.push(changedIndex);
|
||||
}
|
||||
newArr.push(arr[i]);
|
||||
}
|
||||
if (arr[arr.length - 1] < changedIndex) {
|
||||
newArr.push(changedIndex);
|
||||
}
|
||||
}
|
||||
mapNewType.set(newValue, newArr);
|
||||
} else {
|
||||
mapNewType.set(newValue, [changedIndex]);
|
||||
}
|
||||
} else {
|
||||
colRowData.data[newType] = new Map();
|
||||
colRowData.data[newType].set(newValue, [changedIndex])
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
TypedMapCache.prototype.changeData = function (cell, dataOld, dataNew) {
|
||||
const wsId = cell.ws.getId();
|
||||
const data = this.data[wsId];
|
||||
if (data) {
|
||||
const verticalData = data.vertical;
|
||||
const horizontalData = data.horizontal;
|
||||
let oldValue = null;
|
||||
let oldType = null;
|
||||
if (dataOld) {
|
||||
const oldCellValue = dataOld && dataOld.value;
|
||||
oldType = oldCellValue && oldCellValue.type;
|
||||
oldValue = oldType === cElementType.number ? oldCellValue.number : oldCellValue.text;
|
||||
if (oldValue && oldType === cElementType.string) {
|
||||
oldValue = oldValue.toLowerCase();
|
||||
}
|
||||
}
|
||||
let newValue = null;
|
||||
let newType = null;
|
||||
if (dataNew) {
|
||||
newType = dataNew.type;
|
||||
newValue = dataNew.value;
|
||||
if (newValue && newType === cElementType.string) {
|
||||
newValue = newValue.toLowerCase();
|
||||
}
|
||||
}
|
||||
if (oldType === newType && newValue === oldValue) {
|
||||
return;
|
||||
}
|
||||
this.changeAxisData(cell, verticalData, oldValue, oldType, newValue, newType, false);
|
||||
this.changeAxisData(cell, horizontalData, oldValue, oldType, newValue, newType, true);
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
@ -2910,7 +3078,7 @@ function (window, undefined) {
|
||||
this.cacheId = {};
|
||||
this.cacheRanges = {};
|
||||
this.bHor = bHor;
|
||||
this.sortedCache = {data: {}};
|
||||
this.sortedCache = new TypedMapCache();
|
||||
this.typedCache = new TypedCache();
|
||||
this.typedCacheValuesMap = new TypedCache();
|
||||
}
|
||||
@ -3627,80 +3795,7 @@ function (window, undefined) {
|
||||
* @return {Uint32Array} Sorted array of worksheet indices for the specified data type
|
||||
*/
|
||||
VHLOOKUPCache.prototype._getSortedCache = function(ws, rowCol, type, startIndex, endIndex, bHor) {
|
||||
const wsId = ws.Get_Id();
|
||||
const sortedCacheData = this.sortedCache.data;
|
||||
if (!sortedCacheData[wsId]) {
|
||||
sortedCacheData[wsId] = {horizontal: {}, vertical: {}};
|
||||
}
|
||||
/** @type {TypedCacheAxis} */
|
||||
const axisData = bHor ? sortedCacheData[wsId].horizontal : sortedCacheData[wsId].vertical;
|
||||
if (!axisData[rowCol]) {
|
||||
axisData[rowCol] = {start: startIndex, end: endIndex, data: {}};
|
||||
const c1 = bHor ? startIndex : rowCol;
|
||||
const r1 = bHor ? rowCol : startIndex;
|
||||
const c2 = bHor ? endIndex : rowCol;
|
||||
const r2 = bHor ? rowCol : endIndex;
|
||||
const fullRange = ws.getRange3(r1, c1, r2, c2);
|
||||
fullRange._foreachNoEmpty(function (cell, r, c) {
|
||||
const value = checkTypeCell(cell, true);
|
||||
const index = bHor ? c : r;
|
||||
if (!axisData[rowCol].data[value.type]) {
|
||||
axisData[rowCol].data[value.type] = new Map();
|
||||
}
|
||||
const map = axisData[rowCol].data[value.type];
|
||||
if (!map.has(value.value)) {
|
||||
map.set(value.value, []);
|
||||
}
|
||||
const arr = axisData[rowCol].data[value.type].get(value.value);
|
||||
arr.push(index);
|
||||
});
|
||||
axisData[rowCol].start = startIndex;
|
||||
axisData[rowCol].end = endIndex;
|
||||
} else {
|
||||
if (startIndex < axisData[rowCol].start) {
|
||||
const c1 = bHor ? startIndex : rowCol;
|
||||
const r1 = bHor ? rowCol : startIndex;
|
||||
const c2 = bHor ? axisData[rowCol].start : rowCol;
|
||||
const r2 = bHor ? rowCol : axisData[rowCol].start;
|
||||
const fullRange = ws.getRange3(r1, c1, r2, c2);
|
||||
fullRange._foreachNoEmpty(function (cell, r, c) {
|
||||
const value = checkTypeCell(cell, true);
|
||||
const index = bHor ? c : r;
|
||||
if (!axisData[rowCol].data[value.type]) {
|
||||
axisData[rowCol].data[value.type] = new Map();
|
||||
}
|
||||
const map = axisData[rowCol].data[value.type];
|
||||
if (!map.has(value.value)) {
|
||||
map.set(value.value, []);
|
||||
}
|
||||
const arr = axisData[rowCol].data[value.type].get(value.value);
|
||||
arr.unshift(index);
|
||||
});
|
||||
axisData[rowCol].start = startIndex;
|
||||
}
|
||||
if (endIndex > axisData[rowCol].end) {
|
||||
const c1 = bHor ? axisData[rowCol].end : rowCol;
|
||||
const r1 = bHor ? rowCol : axisData[rowCol].end;
|
||||
const c2 = bHor ? endIndex : rowCol;
|
||||
const r2 = bHor ? rowCol : endIndex;
|
||||
const fullRange = ws.getRange3(r1, c1, r2, c2);
|
||||
fullRange._foreachNoEmpty(function (cell, r, c) {
|
||||
const value = checkTypeCell(cell, true);
|
||||
const index = bHor ? c : r;
|
||||
if (!axisData[rowCol].data[value.type]) {
|
||||
axisData[rowCol].data[value.type] = new Map();
|
||||
}
|
||||
const map = axisData[rowCol].data[value.type];
|
||||
if (!map.has(value.value)) {
|
||||
map.set(value.value, []);
|
||||
}
|
||||
const arr = axisData[rowCol].data[value.type].get(value.value);
|
||||
arr.push(index);
|
||||
});
|
||||
axisData[rowCol].end = endIndex;
|
||||
}
|
||||
}
|
||||
return axisData[rowCol].data[type];
|
||||
return this.sortedCache.getData(ws, rowCol, type, startIndex, endIndex, bHor);
|
||||
};
|
||||
/**
|
||||
* Retrieves or generates a typed cache containing worksheet indices for approximate match lookups.
|
||||
@ -3815,79 +3910,12 @@ function (window, undefined) {
|
||||
elem.data.results = {};
|
||||
}
|
||||
}
|
||||
const sortedCacheData = this.sortedCache.data
|
||||
const data = sortedCacheData[wsId];
|
||||
if (data) {
|
||||
const verticalData = data.vertical;
|
||||
const horizontalData = data.horizontal;
|
||||
const colData = verticalData[cell.nCol];
|
||||
if (colData && cell.nRow >= colData.start && cell.nRow <= colData.end) {
|
||||
if (dataOld) {
|
||||
const oldCellValue = dataOld.value;
|
||||
const oldType = oldCellValue.type;
|
||||
if (colData.data[oldType]) {
|
||||
let oldValue = oldType === cElementType.number ? oldCellValue.number : oldCellValue.text;
|
||||
if (oldType.type === cElementType.string) {
|
||||
oldValue = oldValue.toLowerCase();
|
||||
}
|
||||
const mapOldType = colData.data[oldType];
|
||||
if (mapOldType.has(oldValue)) {
|
||||
const arr = mapOldType.get(oldValue);
|
||||
if (arr.length === 1) {
|
||||
mapOldType.delete(oldValue);
|
||||
} else {
|
||||
const newArr = [];
|
||||
for (let i = 0; i < arr.length; i += 1) {
|
||||
if (arr[i] !== cell.nRow) {
|
||||
newArr.push(arr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const newType = dataNew.type;
|
||||
let newValue = dataNew.value;
|
||||
if (newType === cElementType.string) {
|
||||
newValue = newValue.toLowerCase();
|
||||
}
|
||||
const mapNewType = colData.data[newType];
|
||||
if (mapNewType) {
|
||||
if (mapNewType.has(newValue)) {
|
||||
const arr = mapNewType.get(newValue);
|
||||
const newArr = [];
|
||||
if (arr.length === 1) {
|
||||
newArr.push(arr[0]);
|
||||
cell.nRow > arr[0] ? newArr.push(cell.nRow) : newArr.unshift(cell.nRow);
|
||||
} else {
|
||||
if (arr[0] < cell.nRow) {
|
||||
newArr.push(cell.nRow);
|
||||
}
|
||||
for(let i = 1; i < arr.length; i += 1) {
|
||||
if (arr[i] < cell.nRow && arr[i - 1] > cell.nRow) {
|
||||
newArr.push(cell.nRow);
|
||||
}
|
||||
newArr.push(arr[i]);
|
||||
}
|
||||
if (arr[arr.length - 1] < cell.nRow) {
|
||||
newArr.push(cell.nRow);
|
||||
}
|
||||
}
|
||||
mapNewType.set(newValue, newArr);
|
||||
} else {
|
||||
mapNewType.set(newValue, [cell.nRow]);
|
||||
}
|
||||
} else {
|
||||
colData.data[newType] = new Map();
|
||||
colData.data[newType].set(newValue, [cell.nRow])
|
||||
}
|
||||
}
|
||||
}
|
||||
this.sortedCache.changeData(cell, dataOld, dataNew);
|
||||
};
|
||||
VHLOOKUPCache.prototype.clean = function () {
|
||||
this.cacheId = {};
|
||||
this.cacheRanges = {};
|
||||
this.sortedCache = {data: {}};
|
||||
this.sortedCache = new TypedMapCache();
|
||||
this.typedCache.clean();
|
||||
this.typedCacheValuesMap.clean();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user