Filter implementation progress

This commit is contained in:
Bán Dénes 2022-01-03 14:43:45 +01:00
parent 534ac4b75d
commit a7f333c9bc

View file

@ -6,17 +6,41 @@ const _true = () => true
const _and = arr => p => arr.map(e => e(p)).reduce((a, b) => a && b) const _and = arr => p => arr.map(e => e(p)).reduce((a, b) => a && b)
const _or = arr => p => arr.map(e => e(p)).reduce((a, b) => a || b) const _or = arr => p => arr.map(e => e(p)).reduce((a, b) => a || b)
const similar = (a, b, name, units) => { const similar = (key, reference, name, units) => {
let neg = false let neg = false
if (b.startsWith('-')) { if (reference.startsWith('-')) {
neg = true neg = true
b = b.slice(1) reference = reference.slice(1)
} }
if (b.startsWith('/')) { // support both string or regex as reference
//... let internal_tester = val => (''+val) == reference
if (reference.startsWith('/')) {
const regex_parts = reference.split('/')
regex_parts.shift() // remove starting slash
const flags = regex_parts.pop()
const regex = new RegExp(regex_parts.join('/'), flags)
internal_tester = val => regex.test(''+val)
} }
// support strings, arrays, or objects as key
const external_tester = point => {
const value = u.deep(point, key)
if (a.type(value)() == 'array') {
return value.some(subkey => internal_tester(subkey))
} else if (a.type(value)() == 'object') {
return Object.keys(value).some(subkey => internal_tester(subkey))
} else {
return internal_tester(value)
}
}
// negation happens at the end
if (neg) {
return point => !external_tester(point)
}
return external_tester
} }
const comparators = { const comparators = {
@ -27,28 +51,28 @@ const symbols = Object.keys(comparators)
const simple = (exp, name, units) => { const simple = (exp, name, units) => {
let a = ['meta.name', 'meta.tags'] let keys = ['meta.name', 'meta.tags']
let op = '~' let op = '~'
let b let value
const parts = exp.split(/\s+/g) const parts = exp.split(/\s+/g)
// full case // full case
if (symbols.includes(parts[1])) { if (symbols.includes(parts[1])) {
a = parts[0].split(',') keys = parts[0].split(',')
op = parts[1] op = parts[1]
b = parts.slice(2).join(' ') value = parts.slice(2).join(' ')
// middle case, just an operator spec, default "a" // middle case, just an operator spec, default "keys"
} else if (symbols.includes(parts[0])) { } else if (symbols.includes(parts[0])) {
op = parts[0] op = parts[0]
b = parts.slice(1).join(' ') value = parts.slice(1).join(' ')
// basic case, only "b" // basic case, only "value"
} else { } else {
b = exp value = exp
} }
return comparators[op](a, b, name, units) return point => keys.some(key => comparators[op](key, value, name, units))
} }
const complex = (config, name, units, aggregator=_and) => { const complex = (config, name, units, aggregator=_and) => {
@ -78,9 +102,11 @@ const complex = (config, name, units, aggregator=_and) => {
exports.parse = (config, name, points={}, units={}) => { exports.parse = (config, name, points={}, units={}) => {
// if a filter decl is an object, it is an anchor
if (a.type(config)() == 'object') { if (a.type(config)() == 'object') {
return [anchor(config, name, points)(units)] return [anchor(config, name, points)(units)]
} }
// otherwise, it is treated as a condition to filter all available points
return Object.values(points).filter(complex(config, name, units)) return Object.values(points).filter(complex(config, name, units))
} }