Skip to content

Commit

Permalink
gratuitous functional rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
junosuarez committed Apr 30, 2013
1 parent ed7e008 commit 2740621
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 56 deletions.
86 changes: 34 additions & 52 deletions index.js
@@ -1,3 +1,4 @@
var funderscore = require('funderscore')
// type Match: {
// path: Array<String>,
// key: String,
Expand All @@ -6,70 +7,51 @@
// }

// (selectors: String|Array<String>, obj: Object) => Array<Match>
// or
// (selectors: String|Array<String>) => (obj: Object) => Array<Match>
var match = function (selectors, obj) {

// or (selectors: String|Array<String>) => (obj: Object) => Array<Match>
module.exports = function match (selectors, obj) {
selectors = [].concat(selectors).map(function (selector) {
return selector.split('.')
})

var fn = function (document) {

var matches = []
var pathSeg
var seg = document
var stack = [{path: [], value: document, depth: -1}]
var node

// breadth-first search
while(node = stack.pop()) {

// full selector match
if(selectors.some(exactMatch(node))) {

// in ES6, I would so yield.
matches.push({
path: node.path,
value: node.value,
parent: node.parent,
key: node.path[node.path.length - 1]})
continue
}

// first node or partial match
if(node.depth === -1 || selectors.some(partialMatch(node))) {

for(var child in node.value) {
stack.push({
path: node.path.concat(child),
value: node.value[child],
parent: node.value,
depth: node.depth + 1
})
}
}

}
return matches
}

return obj ? fn(obj) : fn
return obj ? findMatches(obj, selectors)
: function (obj) { return findMatches(obj, selectors) }
}

function exactMatch(node) {
var len = node.path.length
function exactMatch(path) {
return function (selector) {
return len === selector.length && node.path.every(function (segment, i) {
return path.length === selector.length && path.every(function (segment, i) {
return selector[i] === '*' || selector[i] === segment
})
}
}

function partialMatch(node) {
var i = node.depth
function partialMatch(path) {
var i = path.length - 1
return function (selector) {
return selector[i] === '*' || selector[i] === node.path[node.depth]
return selector[i] === '*' || selector[i] === path[i]
}
}
module.exports = match

function findMatches(obj, selectors, path, parent) {
if (path === void 0) { path = [] }

// full selector match
if(selectors.some(exactMatch(path))) {
return {
path: path,
value: obj,
parent: parent,
key: path[path.length - 1]
}
}

// first node or partial match
if(!parent || selectors.some(partialMatch(path))) {
return funderscore.flatMap(obj, function (val, key) {
return findMatches(val, selectors, path.concat(key), obj)
})
}

// default
return []
}
7 changes: 6 additions & 1 deletion package.json
Expand Up @@ -19,12 +19,17 @@
"match",
"pattern"
],
"contributors": ["jden <jason@denizac.org>"],
"contributors": [
"jden <jason@denizac.org>"
],
"author": "Agile Diagnosis <hello@agilediagnosis.com>",
"license": "MIT",
"readmeFilename": "README.md",
"devDependencies": {
"chai": "~1.6.0",
"mocha": "~1.9.0"
},
"dependencies": {
"funderscore": "~0.2.0"
}
}
7 changes: 4 additions & 3 deletions test/test.match.js
Expand Up @@ -92,7 +92,7 @@ describe('match', function () {
{path: ['animals','owl','size'], value: 2, parent: {size: 2}, key: 'size'},
{path: ['animals','blue whale','size'], value: 80, parent: {size: 80}, key: 'size'},
{path: ['animals','megalodon','size'], value: 100, parent: {size: 100}, key: 'size'}
].reverse(/* order doesnt actually matter */))
])
})

it('works on arrays', function () {
Expand All @@ -103,8 +103,9 @@ describe('match', function () {
m.should.deep.equal([
{ path: [ 'a', '2', 'c' ], value: 3, parent: {c: 3}, key: 'c' },
{ path: [ 'a', '1', 'c' ], value: 2, parent: {c: 2}, key: 'c' },
{ path: [ 'a', '0', 'c' ], value: 1, parent: {c: 1}, key: 'c' } ])
})
{ path: [ 'a', '0', 'c' ], value: 1, parent: {c: 1}, key: 'c' }
].reverse())
})

it('works with multiple wildcards', function () {
var m = match('a.*.c.*')({
Expand Down

0 comments on commit 2740621

Please sign in to comment.