separate filter functions

This commit is contained in:
Timo Hocker 2020-11-05 07:50:27 +01:00
parent 1162664263
commit bbcd2050e7
3 changed files with 119 additions and 114 deletions

114
filter.js Normal file
View File

@ -0,0 +1,114 @@
'use strict';
function get_element_field (element, carried_data, field) {
if (typeof carried_data[field] !== 'undefined')
return carried_data[field];
return element[field];
}
function check_filter (filter, e, carried_data) {
if (typeof filter.function !== 'undefined')
return filter.function ({ ...e, ...carried_data });
const search_str = Array.isArray (filter.field)
? filter.field.map ((f) => get_element_field (e, carried_data, f))
.filter ((v) => typeof v !== 'undefined')
.join (' ')
: get_element_field (e, carried_data, filter.field);
return filter.filter.test (search_str);
}
function check_filters (filters, e, carried_data, or = false) {
for (const filter of filters) {
let res = false;
if (Array.isArray (filter.or))
res = check_filters (filter.or, e, carried_data, true);
else
res = check_filter (filter, e, carried_data);
if (or && res)
return true;
if (!res && !or)
return false;
}
return !or;
}
/**
* @typedef Filter
* @type {object}
* @property {string|string[]} field - fields to apply filter on
* @property {RegExp} filter - filter
*/
/**
* @typedef FilterFunction
* @type {object}
* @property {function} function - function to test element for match
*/
/**
* @typedef FilterOrGroup
* @type {object}
* @property {FilterType[]} or - create an OR group of filters
*/
/**
* @typedef FilterType
* @type {Filter|FilterFunction|FilterOrGroup}
*/
/**
* filter nested objects
*
* @param {Array<object>} input object to filter
* @param {FilterType[]} filters filters
* @param {string[]} carry carry data to children to match
* @param {object} carried_data internal: carried data
* @returns {Array<object>} filtered data
*/
function recursive_filter (
input,
filters,
children_key = 'children',
carry = [],
carried_data = {}
) {
const data = [ ...input ];
const filtered = [];
for (const c of carry) {
if (typeof carried_data[c] !== 'string')
carried_data[c] = '';
}
for (let i = 0; i < data.length; i++) {
const e = { ...data[i] };
data[i] = e;
const sub_carry = { ...carried_data };
for (const c of carry) {
if (typeof e[c] !== 'undefined')
sub_carry[c] += `${sub_carry[c].length > 0 ? ' ' : ''}${e[c]}`;
}
if (check_filters (filters, e, sub_carry)) {
filtered.push (e);
}
else {
if (typeof e[children_key] === 'undefined')
continue;
e[children_key] = recursive_filter (
e[children_key],
filters,
children_key,
carry,
sub_carry
);
if (e[children_key].length > 0)
filtered.push (e);
}
}
return filtered;
}
module.exports = recursive_filter;

113
index.js
View File

@ -7,6 +7,8 @@
'use strict';
const recursive_filter = require ('./filter');
/**
* truncates a floating point number
*
@ -78,117 +80,6 @@ function is_nil (obj) {
|| (typeof obj === 'number' && isNaN (obj));
}
function get_element_field (element, carried_data, field) {
if (typeof carried_data[field] !== 'undefined')
return carried_data[field];
return element[field];
}
function check_filter (filter, e, carried_data) {
if (typeof filter.function !== 'undefined')
return filter.function ({ ...e, ...carried_data });
const search_str = Array.isArray (filter.field)
? filter.field.map ((f) => get_element_field (e, carried_data, f))
.filter ((v) => typeof v !== 'undefined')
.join (' ')
: get_element_field (e, carried_data, filter.field);
return filter.filter.test (search_str);
}
function check_filters (filters, e, carried_data, or = false) {
for (const filter of filters) {
let res = false;
if (Array.isArray (filter.or))
res = check_filters (filter.or, e, carried_data, true);
else
res = check_filter (filter, e, carried_data);
if (or && res)
return true;
if (!res && !or)
return false;
}
return !or;
}
/**
* @typedef Filter
* @type {object}
* @property {string|string[]} field - fields to apply filter on
* @property {RegExp} filter - filter
*/
/**
* @typedef FilterFunction
* @type {object}
* @property {function} function - function to test element for match
*/
/**
* @typedef FilterOrGroup
* @type {object}
* @property {FilterType[]} or - create an OR group of filters
*/
/**
* @typedef FilterType
* @type {Filter|FilterFunction|FilterOrGroup}
*/
/**
* filter nested objects
*
* @param {Array<object>} input object to filter
* @param {FilterType[]} filters filters
* @param {string[]} carry carry data to children to match
* @param {object} carried_data internal: carried data
* @returns {Array<object>} filtered data
*/
function recursive_filter (
input,
filters,
children_key = 'children',
carry = [],
carried_data = {}
) {
const data = [ ...input ];
const filtered = [];
for (const c of carry) {
if (typeof carried_data[c] !== 'string')
carried_data[c] = '';
}
for (let i = 0; i < data.length; i++) {
const e = { ...data[i] };
data[i] = e;
const sub_carry = { ...carried_data };
for (const c of carry) {
if (typeof e[c] !== 'undefined')
sub_carry[c] += `${sub_carry[c].length > 0 ? ' ' : ''}${e[c]}`;
}
if (check_filters (filters, e, sub_carry)) {
filtered.push (e);
}
else {
if (typeof e[children_key] === 'undefined')
continue;
e[children_key] = recursive_filter (
e[children_key],
filters,
children_key,
carry,
sub_carry
);
if (e[children_key].length > 0)
filtered.push (e);
}
}
return filtered;
}
module.exports = {
truncate_decimal,
try_parse_json,

View File

@ -1,6 +1,6 @@
{
"name": "@sapphirecode/utilities",
"version": "1.8.7",
"version": "1.8.8",
"main": "index.js",
"author": {
"name": "Timo Hocker",
@ -36,8 +36,8 @@
},
"files": [
"LICENSE",
"index.js",
"index.d.ts"
"*.js",
"*.d.ts"
],
"engines": {
"node": ">=10"