Skip to content
Browse files

rewrite for more imperative code

  • Loading branch information...
1 parent f969cd8 commit 663a3f54ca8b9d2713f3a3d75a98af9e80bcb1f9 @substack committed
Showing with 64 additions and 39 deletions.
  1. +62 −37 index.js
  2. +2 −2 test/last.js
View
99 index.js
@@ -1,45 +1,70 @@
-var concatMap = require('concat-map');
-
-module.exports = function pathway (obj, path) {
- return path.reduce(function (nodes, p, ip) {
- if (typeof p === 'function') {
- return withFilter(nodes, p)
+module.exports = function pathway (root, keys) {
+ var length = keys.length;
+ var matches = [];
+
+ (function walk (node, index, key) {
+ var last = index === length - 1;
+ if (key === undefined) key = keys[index];
+ var ktype = typeof key;
+ var ntype = typeof node;
+
+ function check (k, v) {
+ if (ktype === 'boolean') {
+ if (key) walk(v, index + 1);
+ }
+ else if (ktype === 'function') {
+ if (key(v, k)) walk(v, index + 1);
+ }
+ else if (isRegExp(key)) {
+ if (key.test(k)) walk(v, index + 1);
+ }
+ else {
+ if (key === k) walk(v, index + 1);
+ }
+ }
+
+ if (Array.isArray(key)) {
+ for (var i = 0, l = key.length; i < l; i++) {
+ walk(node, index, key[i]);
+ }
}
- else if (typeof p === 'boolean') {
- return withFilter(nodes, function () { return p });
+ else if (ntype === 'object'
+ && (ktype === 'string' || ktype === 'number')) {
+ if (!(key in node)) {}
+ else if (last) matches.push(node[key])
+ else walk(node[key], index + 1)
}
- else if (isRegExp(p)) {
- return withFilter(nodes, function (key) { return p.test(key) })
+ else if (Array.isArray(node)) {
+ for (var i = 0, l = node.length; i < l; i++) {
+ var v = node[i];
+ check(i, v);
+ }
}
- else if (Array.isArray(p)) {
- return withFilter(nodes, function (key) {
- for (var i = 0; i < p.length; i++) {
- if (isRegExp(p[i]) && p[i].test(key)) {
- return true;
- }
- else if (p[i] === key) return true
- }
- return false;
- });
+ else if (ntype === 'object') {
+ var keys_ = Object.keys(node);
+ for (var i = 0, l = keys_.length; i < l; i++) {
+ var k = keys_[i];
+ var v = node[k];
+ check(k, v);
+ }
}
- else {
- return concatMap(nodes, function (node, ix) {
- if (!node[p]) return [];
- return [ node[p] ];
- })
+ else if (last) {
+ if (ktype === 'boolean') {
+ if (key) matches.push(node);
+ }
+ else if (ktype === 'function') {
+ if (key(node)) matches.push(node);
+ }
+ else if (isRegExp(key)) {
+ if (key.test(node)) matches.push(node);
+ }
+ else if (key === node) {
+ matches.push(node);
+ }
}
- }, [ obj ]);
-};
-
-function withFilter (nodes, fn) {
- return concatMap(nodes, function (node) {
- if (typeof node !== 'object') return [];
-
- return Object.keys(node)
- .filter(function (key, ix) { return fn(key, node[key]) })
- .map(function (key) { return node[key] })
- ;
- });
+ })(root, 0);
+
+ return matches;
}
function isRegExp (x) {
View
4 test/last.js
@@ -4,13 +4,13 @@ var test = require('tap').test;
test('last element string', function (t) {
var rows = [ { location: 'Oakland, CA' }, { location: 'Portland, OR' } ];
var xs = pathway(rows, [ true, 'location', 'Oakland, CA' ]);
- t.deepEqual(xs, [ { location: 'Oakland, CA' } ]);
+ t.deepEqual(xs, [ 'Oakland, CA' ]);
t.end();
});
test('last element regexp', function (t) {
var rows = [ { location: 'Oakland, CA' }, { location: 'Portland, OR' } ];
var xs = pathway(rows, [ true, 'location', /\boakland\b/i ]);
- t.deepEqual(xs, [ { location: 'Oakland, CA' } ]);
+ t.deepEqual(xs, [ 'Oakland, CA' ]);
t.end();
});

0 comments on commit 663a3f5

Please sign in to comment.
Something went wrong with that request. Please try again.