const every = (list, fn) => { for(let i = 0, len = list.length; i < len; i++) { if(!fn(list[i])) return []; } return list; } const assert = (val1, val2) => { if (val1 !== val2) { throw new Error(`${val1.toString()} is not ${val2.toString()}`) } } const l = [1, 2, 3, 0] assert(every(l, i => i < 5), l); assert(every(l, i => i === 0).length, 0); const EQ = (selector, criteria) => { return (...list) => { var r = list.filter(item => selector(item) === criteria) console.log(r, 'eq') return r; } } assert(EQ(i => i, 1)(...l).length, 1); assert(EQ(i => i, 5)(...l).length, 0); const OR = (...filters) => { console.log('#', filters) return (...list) => list.filter(item => { const r = filters.filter(f => { return f(item).length > 0 } ) console.log('or', r, filters, item) return r; }) } assert( OR( EQ(i => i, 1), EQ(i => i, 3), )(...l).length, 2 ) /**assert( OR( EQ(i => i, 1), EQ(i => i, 1), OR( EQ(i => i, 1), EQ(i => i, 1), ), )(...l).length, 1 ) const AND = (...filters) => (...list) => { const end = every(list, item => { const r = every(filters, f => f(item).length > 0 ).length > 0 console.log('and', r) return r }) console.log('andend', end) return end; }; const yourFilter = AND( OR( EQ(i => i.name, 'ben'), EQ(i => i.name, 'y'), ), OR( EQ(i => i.id, 1), EQ(i => i.id, 2), ), EQ(i => i.id, 1), /*EQUALS('id', 3), EQUALS('name', 'sep'), ); console.log('=', yourFilter( {id: 1, name: 'ben'}, {id: 2, name: 'y'}, {id: 3, name: 'z'}, ) )**/