carry values between filter runs

This commit is contained in:
Timo Hocker 2020-06-30 11:20:09 +02:00
parent 141c698351
commit 092e84d8bb
4 changed files with 101 additions and 15 deletions

2
Jenkinsfile vendored
View File

@ -5,7 +5,7 @@ pipeline {
VERSION = VersionNumber([ VERSION = VersionNumber([
versionNumberString: versionNumberString:
'${BUILDS_ALL_TIME}', '${BUILDS_ALL_TIME}',
versionPrefix: '1.6.', versionPrefix: '1.7.',
worstResultForIncrement: 'SUCCESS' worstResultForIncrement: 'SUCCESS'
]) ])
} }

View File

@ -118,9 +118,9 @@ const result = util.recursive_filter(
[ [
{ {
filter: /foo bar/iu, filter: /foo bar/iu,
field: ['name', 'name_2'] // fields will be joined with a space in between field: ['name', 'name_2'], // fields will be joined with a space in between
// {name: 'foo', name_2: 'bar'} will become 'foo bar' // {name: 'foo', name_2: 'bar'} will become 'foo bar'
} },
] ]
); );
``` ```
@ -134,7 +134,7 @@ const result = util.recursive_filter(
{ {
filter: /foo bar/iu, filter: /foo bar/iu,
field: 'name' field: 'name'
}, },
{ {
or: [ or: [
{ filter: /foo/u, field: 'bar' }, { filter: /foo/u, field: 'bar' },
@ -145,6 +145,38 @@ const result = util.recursive_filter(
); );
``` ```
field values can be carried to filter runs on children to filter over the entire tree instead of just one element
```js
const to_filter = [
{
name: 'foo',
children: [
{ name: 'bar' },
{ name: 'baz' },
{ foo: 'bar' }
]
}
];
const res = util.recursive_filter (
to_filter,
[ { field: 'name', filter: /foo bar/ui } ], // values will be separaed by a space
'children',
[ 'name' ] // specify which fields should be carried
// the filters will receive the carried values instead of the plain fields
);
/* result:
[
{
name: 'foo',
children: [ { name: 'bar' } ]
}
]
*/
```
## License ## License

View File

@ -78,23 +78,29 @@ function is_nil (obj) {
|| (typeof obj === 'number' && isNaN (obj)); || (typeof obj === 'number' && isNaN (obj));
} }
function check_filter (filter, e) { 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) {
const search_str = Array.isArray (filter.field) const search_str = Array.isArray (filter.field)
? filter.field.map ((f) => e[f]) ? filter.field.map ((f) => get_element_field (e, carried_data, f))
.filter ((v) => typeof v !== 'undefined') .filter ((v) => typeof v !== 'undefined')
.join (' ') .join (' ')
: e[filter.field]; : get_element_field (e, carried_data, filter.field);
return filter.filter.test (search_str); return filter.filter.test (search_str);
} }
function check_filters (filters, e, or = false) { function check_filters (filters, e, carried_data, or = false) {
for (const filter of filters) { for (const filter of filters) {
let res = false; let res = false;
if (Array.isArray (filter.or)) if (Array.isArray (filter.or))
res = check_filters (filter.or, e, true); res = check_filters (filter.or, e, carried_data, true);
else else
res = check_filter (filter, e); res = check_filter (filter, e, carried_data);
if (or && res) if (or && res)
return true; return true;
@ -120,17 +126,36 @@ function check_filters (filters, e, or = false) {
/** /**
* filter nested objects * filter nested objects
* *
* @param {Array<object>} input * @param {Array<object>} input object to filter
* @param {(Filter|FilterOrGroup)[]} filters * @param {(Filter|FilterOrGroup)[]} filters filters
* @param {string[]} carry carry data to children to match
* @param {object} carried_data internal: carried data
* @returns {Array<object>} filtered data * @returns {Array<object>} filtered data
*/ */
function recursive_filter (input, filters, children_key = 'children') { function recursive_filter (
input,
filters,
children_key = 'children',
carry = [],
carried_data = {}
) {
const data = [ ...input ]; const data = [ ...input ];
const filtered = []; const filtered = [];
for (const c of carry) {
if (typeof carried_data[c] !== 'string')
carried_data[c] = '';
}
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
const e = { ...data[i] }; const e = { ...data[i] };
data[i] = e; data[i] = e;
if (check_filters (filters, 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); filtered.push (e);
} }
else { else {
@ -139,7 +164,9 @@ function recursive_filter (input, filters, children_key = 'children') {
e[children_key] = recursive_filter ( e[children_key] = recursive_filter (
e[children_key], e[children_key],
filters, filters,
children_key children_key,
carry,
sub_carry
); );
if (e[children_key].length > 0) if (e[children_key].length > 0)
filtered.push (e); filtered.push (e);

View File

@ -225,3 +225,30 @@ test ('recursive filter with or group', (t) => {
t.deepEqual (res, to_filter.slice (0, 2)); t.deepEqual (res, to_filter.slice (0, 2));
}); });
test ('recursive filter carry field', (t) => {
const to_filter = [
{
name: 'foo',
children: [
{ name: 'bar' },
{ name: 'baz' },
{ foo: 'bar' }
]
}
];
const res = util.recursive_filter (
to_filter,
[ { field: 'name', filter: /foo bar/ui } ],
'children',
[ 'name' ]
);
t.deepEqual (res, [
{
name: 'foo',
children: [ { name: 'bar' } ]
}
]);
});