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([
versionNumberString:
'${BUILDS_ALL_TIME}',
versionPrefix: '1.6.',
versionPrefix: '1.7.',
worstResultForIncrement: 'SUCCESS'
])
}

View File

@ -118,9 +118,9 @@ const result = util.recursive_filter(
[
{
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'
}
},
]
);
```
@ -134,7 +134,7 @@ const result = util.recursive_filter(
{
filter: /foo bar/iu,
field: 'name'
},
},
{
or: [
{ 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

View File

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

View File

@ -225,3 +225,30 @@ test ('recursive filter with or group', (t) => {
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' } ]
}
]);
});