filter groups
This commit is contained in:
parent
7939aaf3a7
commit
c9e419d8e9
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@ -5,7 +5,7 @@ pipeline {
|
|||||||
VERSION = VersionNumber([
|
VERSION = VersionNumber([
|
||||||
versionNumberString:
|
versionNumberString:
|
||||||
'${BUILDS_ALL_TIME}',
|
'${BUILDS_ALL_TIME}',
|
||||||
versionPrefix: '1.5.',
|
versionPrefix: '1.6.',
|
||||||
worstResultForIncrement: 'SUCCESS'
|
worstResultForIncrement: 'SUCCESS'
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
25
README.md
25
README.md
@ -1,6 +1,6 @@
|
|||||||
# @sapphirecode/utilities
|
# @sapphirecode/utilities
|
||||||
|
|
||||||
version: 1.5.x
|
version: 1.6.x
|
||||||
|
|
||||||
small utility functions to make much needed features easier to work with
|
small utility functions to make much needed features easier to work with
|
||||||
|
|
||||||
@ -118,13 +118,34 @@ const result = util.recursive_filter(
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
filter: /foo bar/iu,
|
filter: /foo bar/iu,
|
||||||
fields: ['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'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
filter groups can be used to connect filters with OR
|
||||||
|
|
||||||
|
```js
|
||||||
|
const result = util.recursive_filter(
|
||||||
|
[...],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
filter: /foo bar/iu,
|
||||||
|
field: 'name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
or: [
|
||||||
|
{ filter: /foo/u, field: 'bar' },
|
||||||
|
{ filter: /bar/u, field: 'bar' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT © Timo Hocker <timo@scode.ovh>
|
MIT © Timo Hocker <timo@scode.ovh>
|
||||||
|
47
index.js
47
index.js
@ -78,19 +78,45 @@ function is_nil (obj) {
|
|||||||
|| (typeof obj === 'number' && isNaN (obj));
|
|| (typeof obj === 'number' && isNaN (obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
function to_search_string (element, field) {
|
function check_filter (filter, e) {
|
||||||
return Array.isArray (field)
|
const search_str = Array.isArray (filter.field)
|
||||||
? field.map ((f) => element[f])
|
? filter.field.map ((f) => e[f])
|
||||||
.filter ((v) => typeof v !== 'undefined')
|
.filter ((v) => typeof v !== 'undefined')
|
||||||
.join (' ')
|
.join (' ')
|
||||||
: element[field];
|
: e[filter.field];
|
||||||
|
|
||||||
|
return filter.filter.test (search_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function check_filters (filters, e, or = false) {
|
||||||
|
for (const filter of filters) {
|
||||||
|
let res = false;
|
||||||
|
if (Array.isArray (filter.or))
|
||||||
|
res = check_filters (filter.or, e, true);
|
||||||
|
else
|
||||||
|
res = check_filter (filter, e);
|
||||||
|
|
||||||
|
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
|
||||||
|
* @property {Filter[]} or - create an OR group of filters
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* filter nested objects
|
* filter nested objects
|
||||||
*
|
*
|
||||||
* @param {Array<object>} input
|
* @param {Array<object>} input
|
||||||
* @param {Array<{field: string, filter: RegExp}>} filters
|
* @param {Filter[]} filters
|
||||||
* @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') {
|
||||||
@ -99,16 +125,7 @@ function recursive_filter (input, filters, children_key = 'children') {
|
|||||||
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;
|
||||||
let match = true;
|
if (check_filters (filters, e)) {
|
||||||
for (const filter of filters) {
|
|
||||||
const search_str = to_search_string (e, filter.field);
|
|
||||||
|
|
||||||
if (!filter.filter.test (search_str)) {
|
|
||||||
match = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (match) {
|
|
||||||
filtered.push (e);
|
filtered.push (e);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -204,3 +204,24 @@ test ('recursive filter undefined multifield', (t) => {
|
|||||||
);
|
);
|
||||||
t.deepEqual (res, []);
|
t.deepEqual (res, []);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test ('recursive filter with or group', (t) => {
|
||||||
|
const to_filter = [
|
||||||
|
{ name: 'foo' },
|
||||||
|
{ name: 'bar' },
|
||||||
|
{ name: 'baz' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const filter = [
|
||||||
|
{
|
||||||
|
or: [
|
||||||
|
{ field: 'name', filter: /foo/u },
|
||||||
|
{ field: 'name', filter: /bar/u }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = util.recursive_filter (to_filter, filter);
|
||||||
|
|
||||||
|
t.deepEqual (res, to_filter.slice (0, 2));
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user