From 99bfed8b688be24a63949d7d70fe3a6cf8caff56 Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Sun, 19 May 2019 19:03:14 +0800 Subject: [PATCH 01/14] weektest-2019.5.19 --- 2019/May/Week3/filter.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/2019/May/Week3/filter.js b/2019/May/Week3/filter.js index 6165447..5dce100 100644 --- a/2019/May/Week3/filter.js +++ b/2019/May/Week3/filter.js @@ -22,5 +22,38 @@ * filter(users, 'active'); */ module.exports = function filter(collection, predicate) { + const result = []; + if (!collection || !predicate) return result; + if (typeof collection != 'object') return result; + + if (typeof collection == 'object') collection = Object.values(collection); + + if (typeof predicate === 'function') { + collection.forEach(function (item) { + if (predicate(item)) result.push(item); + }); + } + + if (typeof predicate === 'object') { + collection.forEach(function (item) { + var has = true; + + for (var key in predicate) { + if ((item[key] == 'undefined') || (item[key] != predicate[key])) has = false; + } + + if (has) result.push(item); + }); + } + + if (typeof predicate === 'string') { + collection.forEach(function (item) { + if (item[predicate] != 'undefined' && item[predicate]) { + result.push(item); + } + }); + } + + return result; }; From 6a9c33a2f4a912d6ff13a0a439c1535149b44643 Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Sun, 19 May 2019 21:53:32 +0800 Subject: [PATCH 02/14] use filter --- 2019/May/Week3/filter.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/2019/May/Week3/filter.js b/2019/May/Week3/filter.js index 5dce100..7f0fca2 100644 --- a/2019/May/Week3/filter.js +++ b/2019/May/Week3/filter.js @@ -22,7 +22,7 @@ * filter(users, 'active'); */ module.exports = function filter(collection, predicate) { - const result = []; + let result = []; if (!collection || !predicate) return result; if (typeof collection != 'object') return result; @@ -30,13 +30,11 @@ module.exports = function filter(collection, predicate) { if (typeof collection == 'object') collection = Object.values(collection); if (typeof predicate === 'function') { - collection.forEach(function (item) { - if (predicate(item)) result.push(item); - }); + result = collection.filter(item => predicate(item)); } if (typeof predicate === 'object') { - collection.forEach(function (item) { + collection.forEach(item => { var has = true; for (var key in predicate) { @@ -48,11 +46,7 @@ module.exports = function filter(collection, predicate) { } if (typeof predicate === 'string') { - collection.forEach(function (item) { - if (item[predicate] != 'undefined' && item[predicate]) { - result.push(item); - } - }); + result = collection.filter(item => item[predicate]); } return result; From f165e283191e33674b379c1dfa86fce7a20fe13c Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Sun, 19 May 2019 22:31:18 +0800 Subject: [PATCH 03/14] fix lint bug --- 2019/May/Week3/filter.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/2019/May/Week3/filter.js b/2019/May/Week3/filter.js index 7f0fca2..5617364 100644 --- a/2019/May/Week3/filter.js +++ b/2019/May/Week3/filter.js @@ -25,28 +25,28 @@ module.exports = function filter(collection, predicate) { let result = []; if (!collection || !predicate) return result; - if (typeof collection != 'object') return result; + if (typeof collection !== 'object') return result; - if (typeof collection == 'object') collection = Object.values(collection); + const coll = typeof collection === 'object' ? Object.values(collection) : collection; if (typeof predicate === 'function') { - result = collection.filter(item => predicate(item)); + result = coll.filter(item => predicate(item)); } if (typeof predicate === 'object') { - collection.forEach(item => { - var has = true; + coll.forEach(item => { + let has = true; - for (var key in predicate) { - if ((item[key] == 'undefined') || (item[key] != predicate[key])) has = false; - } + Object.keys(predicate).forEach(key => { + if ((item[key] === 'undefined') || (item[key] !== predicate[key])) has = false; + }); if (has) result.push(item); }); } if (typeof predicate === 'string') { - result = collection.filter(item => item[predicate]); + result = coll.filter(item => item[predicate]); } return result; From 35414a7d5f6c3155c056155523aa61e539dc57e2 Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Sun, 19 May 2019 23:09:06 +0800 Subject: [PATCH 04/14] commit add idea in gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index ad46b30..af83e12 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ npm-debug.log* yarn-debug.log* yarn-error.log* +# IDE +.idea + # Runtime data pids *.pid From b1263b55e4b8ac43ea14d3e327c7f77addff4035 Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Tue, 21 May 2019 21:02:12 +0800 Subject: [PATCH 05/14] improve program --- 2019/May/Week3/filter.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/2019/May/Week3/filter.js b/2019/May/Week3/filter.js index 5617364..b5fe895 100644 --- a/2019/May/Week3/filter.js +++ b/2019/May/Week3/filter.js @@ -27,22 +27,14 @@ module.exports = function filter(collection, predicate) { if (!collection || !predicate) return result; if (typeof collection !== 'object') return result; - const coll = typeof collection === 'object' ? Object.values(collection) : collection; + const coll = (collection.constructor === Object) ? Object.values(collection) : collection; if (typeof predicate === 'function') { result = coll.filter(item => predicate(item)); } if (typeof predicate === 'object') { - coll.forEach(item => { - let has = true; - - Object.keys(predicate).forEach(key => { - if ((item[key] === 'undefined') || (item[key] !== predicate[key])) has = false; - }); - - if (has) result.push(item); - }); + result = coll.filter(item => (Object.keys(predicate).every(key => item[key] === predicate[key]))); } if (typeof predicate === 'string') { From 1c056fde5b52d310dac098aad3de74e49eba278a Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Sun, 26 May 2019 18:01:52 +0800 Subject: [PATCH 06/14] 2019.05.26-week4-wjx --- 2019/May/Week4/merge-collection.js | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/2019/May/Week4/merge-collection.js b/2019/May/Week4/merge-collection.js index 3546585..5bea64c 100644 --- a/2019/May/Week4/merge-collection.js +++ b/2019/May/Week4/merge-collection.js @@ -32,6 +32,58 @@ * // 按 (o) => o.dim1 合并 * mergeCollection((o) => o.dim1, col1, col2, col3); */ + +function assign(targetPar, ...parameters) { + const target = Object(targetPar); + + parameters.forEach(source => { + Object.keys(source).forEach(key => { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + }); + }); + + return target; +}; + module.exports = function mergeCollection(keys, baseCollection, ...restCollection) { + if (!keys || !baseCollection || !restCollection) return baseCollection; + + const result = []; + let baseColl = baseCollection; + let restColl = restCollection; + let keysArr = keys; + + if (typeof keys === 'string') keysArr = [keys]; + + if (typeof baseCollection === 'object' && !Array.isArray(baseCollection)) { + baseColl = Object.values(baseCollection); + } + + const arrayRestColl = []; + restColl.forEach(item => { + if (typeof item === 'object' && !Array.isArray(item)) { + arrayRestColl.push(Object.values(item)); + } + }); + if (arrayRestColl.length) restColl = arrayRestColl; + + baseColl.forEach(bi => { + let biTmp = bi; + restColl.forEach(rc => { + rc.forEach(ri => { + let match = false; + + if (typeof keysArr === 'object' && Array.isArray(keysArr) && keysArr.every(key => (biTmp[key] === ri[key]))) match = true; + + if (typeof keysArr === 'function' && (keysArr(ri) === keysArr(biTmp))) match = true; + + if (match) biTmp = assign(biTmp, ri); + }); + }); + result.push(biTmp); + }); + return result; }; From a81524f42973842fda903ee8cfeedf7a956c5c86 Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Sun, 26 May 2019 18:47:30 +0800 Subject: [PATCH 07/14] format --- 2019/May/Week4/merge-collection.js | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/2019/May/Week4/merge-collection.js b/2019/May/Week4/merge-collection.js index 5bea64c..5ab8b45 100644 --- a/2019/May/Week4/merge-collection.js +++ b/2019/May/Week4/merge-collection.js @@ -51,37 +51,50 @@ module.exports = function mergeCollection(keys, baseCollection, ...restCollectio if (!keys || !baseCollection || !restCollection) return baseCollection; const result = []; + const arrayRestColl = []; let baseColl = baseCollection; let restColl = restCollection; let keysArr = keys; - if (typeof keys === 'string') keysArr = [keys]; - if (typeof baseCollection === 'object' && !Array.isArray(baseCollection)) { baseColl = Object.values(baseCollection); - } + } - const arrayRestColl = []; restColl.forEach(item => { if (typeof item === 'object' && !Array.isArray(item)) { arrayRestColl.push(Object.values(item)); } }); - if (arrayRestColl.length) restColl = arrayRestColl; + + if (arrayRestColl.length) { + restColl = arrayRestColl; + } + + if (typeof keys === 'string') { + keysArr = [keys]; + } baseColl.forEach(bi => { let biTmp = bi; + restColl.forEach(rc => { rc.forEach(ri => { let match = false; - if (typeof keysArr === 'object' && Array.isArray(keysArr) && keysArr.every(key => (biTmp[key] === ri[key]))) match = true; + if (typeof keysArr === 'object' && Array.isArray(keysArr) && keysArr.every(key => (biTmp[key] === ri[key]))) { + match = true; + } - if (typeof keysArr === 'function' && (keysArr(ri) === keysArr(biTmp))) match = true; + if (typeof keysArr === 'function' && (keysArr(ri) === keysArr(biTmp))) { + match = true; + } - if (match) biTmp = assign(biTmp, ri); + if (match) { + biTmp = assign(biTmp, ri); + } }); }); + result.push(biTmp); }); From 646cc9a2df950e3b7f1b5e31124dd400827c647d Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Sun, 2 Jun 2019 21:08:14 +0800 Subject: [PATCH 08/14] 2019.06.02-week5-wjx --- 2019/May/Week5/flatten-tree.js | 56 +++++++++++++++++++++++++++++ 2019/May/Week5/flatten-tree.test.js | 8 ++--- 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/2019/May/Week5/flatten-tree.js b/2019/May/Week5/flatten-tree.js index 0dff3d1..92ef5f7 100644 --- a/2019/May/Week5/flatten-tree.js +++ b/2019/May/Week5/flatten-tree.js @@ -35,5 +35,61 @@ * ] */ module.exports = function flatten2tree(flattenArr, id = 'id', pid = 'pid', level = 'level', children = 'children') { + if (!Array.isArray(flattenArr)) { + return []; + } + let maxLevel = 0; + let minLevel = 0; + + flattenArr.forEach(item => { + if (maxLevel === 0 || item[level] > maxLevel) { + maxLevel = item[level]; + } + + if (minLevel === 0 || item[level] < minLevel) { + minLevel = item[level]; + } + }); + + let nowLevel = maxLevel; + let currentLevelNodes = []; + let lastLevelNodes = []; + + function buildData() { + lastLevelNodes = currentLevelNodes; + currentLevelNodes = []; + + flattenArr.forEach(it => { + const item = it; + + if (item[level] !== nowLevel) return; + + const node = item[id]; + const pNode = item[pid]; + + if (lastLevelNodes[node]) { + item[children] = lastLevelNodes[node]; + } + + if (!currentLevelNodes[pNode]) { + currentLevelNodes[pNode] = []; + } + + currentLevelNodes[pNode].push(item); + }); + + nowLevel -= 1; + } + + while (nowLevel > (minLevel - 1)) { // 2 > 0 + buildData(); + } + + let tree = []; + currentLevelNodes.forEach(nodes => { + tree = tree.concat(nodes); + }); + + return tree; } diff --git a/2019/May/Week5/flatten-tree.test.js b/2019/May/Week5/flatten-tree.test.js index afa82df..67347cb 100644 --- a/2019/May/Week5/flatten-tree.test.js +++ b/2019/May/Week5/flatten-tree.test.js @@ -1,7 +1,7 @@ const { expect } = require('chai'); const flatten2tree = require('./flatten-tree'); -describe('2019 May Week4 Test: flatten-tree', () => { +describe('2019 May Week5 Test: flatten-tree', () => { it('two level without alias', () => { const flattenArr = [ { id: 1, pid: 0, name: 'a', level: 1 }, @@ -15,7 +15,7 @@ describe('2019 May Week4 Test: flatten-tree', () => { expect(tree[0]).to.have.property('children'); expect(tree[0].children).to.be.an('array'); expect(tree[0].children).to.have.lengthOf(2); - expect(tree[1].children).to.be.undefined; + expect(tree[1].children).to.be.an('undefined'); }); it('two level with alias', () => { @@ -33,10 +33,10 @@ describe('2019 May Week4 Test: flatten-tree', () => { expect(tree[0]).to.have.property('name'); expect(tree[0]).to.have.property('slevel'); expect(tree[0]).to.have.property('items'); - expect(tree[0].children).to.be.undefined; + expect(tree[0].children).to.be.an('undefined'); expect(tree[0].items).to.be.an('array'); expect(tree[0].items).to.have.lengthOf(2); - expect(tree[1].children).to.be.undefined; + expect(tree[1].children).to.be.an('undefined'); }); it('deep level without alias', () => { From 630274fff32e5d6ffc812e4fceb1079b73f10a79 Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Mon, 10 Jun 2019 22:27:02 +0800 Subject: [PATCH 09/14] add func omit --- 2019/Jun/Week2/tree-path.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/2019/Jun/Week2/tree-path.js b/2019/Jun/Week2/tree-path.js index 8421c6a..4fba43e 100644 --- a/2019/Jun/Week2/tree-path.js +++ b/2019/Jun/Week2/tree-path.js @@ -49,7 +49,7 @@ const LOOKUPTYPE = { * ] */ module.exports = function lookupTreePath(tree, predicate, lookupType = LOOKUPTYPE.ONLY_LEAF) { - if (!tree) return []; + if (!tree || !predicate) return []; const lutp = lookupType; let predicateFn = predicate; @@ -59,9 +59,22 @@ module.exports = function lookupTreePath(tree, predicate, lookupType = LOOKUPTYP predicateFn = node => Object.keys(predicate).every(key => (typeof predicate[key] === 'function' ? predicate[key](node[key]) : node[key] === predicate[key])); } + function omit(object, deleteKeys = []) { + const newObj = Array.isArray(object) ? [] : {}; + + /* eslint no-restricted-syntax: "error" */ + for (const key in object) { + if (Object.prototype.hasOwnProperty.call(object, key) && (deleteKeys.indexOf(key) === -1)) { + newObj[key] = (typeof object[key] === "object") ? omit(object[key], deleteKeys) : object[key]; + } + } + + return newObj; + } + function passTree(node, path) { - const currentNode = JSON.parse(JSON.stringify(node)); - if (currentNode.children) delete currentNode.children; + const currentNode = omit(node, ['children']); + path.push(currentNode); if (lutp === LOOKUPTYPE.ONLY_LEAF && !node.children && predicateFn(node)) { From b9f7268e04b6ea56487468cbb8d41bb5e54f86cd Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Tue, 11 Jun 2019 23:08:15 +0800 Subject: [PATCH 10/14] improve code --- 2019/Jun/Week2/tree-path.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/2019/Jun/Week2/tree-path.js b/2019/Jun/Week2/tree-path.js index 4fba43e..4763121 100644 --- a/2019/Jun/Week2/tree-path.js +++ b/2019/Jun/Week2/tree-path.js @@ -51,7 +51,6 @@ const LOOKUPTYPE = { module.exports = function lookupTreePath(tree, predicate, lookupType = LOOKUPTYPE.ONLY_LEAF) { if (!tree || !predicate) return []; - const lutp = lookupType; let predicateFn = predicate; const paths = []; @@ -60,12 +59,12 @@ module.exports = function lookupTreePath(tree, predicate, lookupType = LOOKUPTYP } function omit(object, deleteKeys = []) { - const newObj = Array.isArray(object) ? [] : {}; + const newObj = {}; /* eslint no-restricted-syntax: "error" */ for (const key in object) { - if (Object.prototype.hasOwnProperty.call(object, key) && (deleteKeys.indexOf(key) === -1)) { - newObj[key] = (typeof object[key] === "object") ? omit(object[key], deleteKeys) : object[key]; + if (deleteKeys.indexOf(key) === -1) { + newObj[key] = object[key]; } } @@ -77,12 +76,12 @@ module.exports = function lookupTreePath(tree, predicate, lookupType = LOOKUPTYP path.push(currentNode); - if (lutp === LOOKUPTYPE.ONLY_LEAF && !node.children && predicateFn(node)) { + if (lookupType === LOOKUPTYPE.ONLY_LEAF && !node.children && predicateFn(node)) { paths.push(path); return; } - if (lutp === LOOKUPTYPE.ALWAYS_CHILDREN && node.children && predicateFn(node)) { + if (lookupType === LOOKUPTYPE.ALWAYS_CHILDREN && node.children && predicateFn(node)) { node.children.forEach(cNode => { paths.push([].concat(path, [cNode])); }); @@ -90,7 +89,7 @@ module.exports = function lookupTreePath(tree, predicate, lookupType = LOOKUPTYP return; } - if (lutp === LOOKUPTYPE.WITHOUT_CHILDREN && node.children && predicateFn(node)) { + if (lookupType === LOOKUPTYPE.WITHOUT_CHILDREN && node.children && predicateFn(node)) { paths.push([currentNode]); return; } From 9b7fd0a8a01e37f0c45e6dc9a76480b8db34d2be Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Mon, 17 Jun 2019 20:55:19 +0800 Subject: [PATCH 11/14] 2019.06.17-week3-wjx --- 2019/Jun/Week2/tree-path.js | 115 ++++++++++++++---------------- 2019/Jun/Week2/tree-path.test.js | 10 +++ 2019/Jun/Week3/call-chain.js | 44 ++++++++++++ 2019/Jun/Week3/call-chain.test.js | 51 +++++++++++++ package.json | 5 +- 5 files changed, 163 insertions(+), 62 deletions(-) create mode 100644 2019/Jun/Week3/call-chain.js create mode 100644 2019/Jun/Week3/call-chain.test.js diff --git a/2019/Jun/Week2/tree-path.js b/2019/Jun/Week2/tree-path.js index 4763121..6c3ae17 100644 --- a/2019/Jun/Week2/tree-path.js +++ b/2019/Jun/Week2/tree-path.js @@ -5,6 +5,57 @@ const LOOKUPTYPE = { ALWAYS_CHILDREN: 2, // 父节点满足,则忽略所有子节点 WITHOUT_CHILDREN: 3, +}; + +function correspond(object, predicate) { + if (typeof predicate === 'function') { + return predicate(object); + } + + let isConrrespond = true; + // eslint-disable-next-line no-restricted-syntax + for (const key in predicate) { + if (Object.prototype.hasOwnProperty.call(predicate, key)) { + const val = predicate[key]; + if (typeof val === 'function') { + if (!val(object[key])) { + isConrrespond = false; + break; + } + } else if (object[key] !== val) { + isConrrespond = false; + break; + } + } + } + + return isConrrespond; +} + +function toPath(retArr, tree, prePath, predicate, lookupType) { + tree.forEach(item => { + const cloneItem = { ...item }; + delete cloneItem.children; + + const currentPath = [...prePath]; + currentPath.push(cloneItem); + if (lookupType === LOOKUPTYPE.WITHOUT_CHILDREN) { + if (correspond(item, predicate)) { + retArr.push(currentPath); + } + } else if (lookupType === LOOKUPTYPE.ALWAYS_CHILDREN) { + // 此节点满足,则此节点下的叶子节点全部满足 + if (correspond(item, predicate)) { + toPath(retArr, item.children, currentPath, () => true, LOOKUPTYPE.ONLY_LEAF); + } + } else if (lookupType === LOOKUPTYPE.ONLY_LEAF) { + if (item.children) { + toPath(retArr, item.children, currentPath, predicate, lookupType); + } else if (correspond(item, predicate)) { + retArr.push(currentPath); + } + } + }); } /** @@ -49,65 +100,9 @@ const LOOKUPTYPE = { * ] */ module.exports = function lookupTreePath(tree, predicate, lookupType = LOOKUPTYPE.ONLY_LEAF) { - if (!tree || !predicate) return []; - - let predicateFn = predicate; - const paths = []; - - if (typeof predicate === 'object') { - predicateFn = node => Object.keys(predicate).every(key => (typeof predicate[key] === 'function' ? predicate[key](node[key]) : node[key] === predicate[key])); - } - - function omit(object, deleteKeys = []) { - const newObj = {}; - - /* eslint no-restricted-syntax: "error" */ - for (const key in object) { - if (deleteKeys.indexOf(key) === -1) { - newObj[key] = object[key]; - } - } - - return newObj; - } - - function passTree(node, path) { - const currentNode = omit(node, ['children']); - - path.push(currentNode); - - if (lookupType === LOOKUPTYPE.ONLY_LEAF && !node.children && predicateFn(node)) { - paths.push(path); - return; - } - - if (lookupType === LOOKUPTYPE.ALWAYS_CHILDREN && node.children && predicateFn(node)) { - node.children.forEach(cNode => { - paths.push([].concat(path, [cNode])); - }); - - return; - } - - if (lookupType === LOOKUPTYPE.WITHOUT_CHILDREN && node.children && predicateFn(node)) { - paths.push([currentNode]); - return; - } - - if (node.children) { - node.children.forEach(cNode => { - const newPatch = [].concat(path); - passTree(cNode, newPatch); - }); - } - } - - tree.forEach(node => { - const path = []; - passTree(node, path); - }); - - return paths; -} + const retArr = []; + toPath(retArr, tree, [], predicate, lookupType); + return retArr; +}; module.exports.LOOKUPTYPE = LOOKUPTYPE; diff --git a/2019/Jun/Week2/tree-path.test.js b/2019/Jun/Week2/tree-path.test.js index f2c7797..02e6e3b 100644 --- a/2019/Jun/Week2/tree-path.test.js +++ b/2019/Jun/Week2/tree-path.test.js @@ -100,6 +100,16 @@ describe('2019 Jun Week2 Test: tree-path', () => { [{ id: 2, pid: 0, name: 'b', level: 1 }, { id: 5, pid: 2, name: 'ba', level: 2 }], [{ id: 2, pid: 0, name: 'b', level: 1 }, { id: 6, pid: 2, name: 'bb', level: 2 }], ]); + + expect(lookupTreePath(tree, node => node.name === 'a', ALWAYS_CHILDREN)).to.be.eql([ + [{ id: 1, pid: 0, name: 'a', level: 1 }, { id: 3, pid: 1, name: 'aa', level: 2 }], + [ + { id: 1, pid: 0, name: 'a', level: 1 }, + { id: 4, pid: 1, name: 'ab', level: 2 }, + { id: 8, pid: 4, name: 'aba', level: 3 }, + { id: 9, pid: 8, name: 'abaa', level: 4 }, + ], + ]); }); it('lookup without children by fn', () => { diff --git a/2019/Jun/Week3/call-chain.js b/2019/Jun/Week3/call-chain.js new file mode 100644 index 0000000..ca38abd --- /dev/null +++ b/2019/Jun/Week3/call-chain.js @@ -0,0 +1,44 @@ +/** + * 链式调用 + * + * @param {Function} executor 执行器 + * + * @example + * const cc = new CallChain((method, args) => { + * console.log(method, args); + * }); + * cc.a.b.c(1, 2, 3); + * + * method: a.b.c + * args: [1, 2, 3] + */ +function CallChain(executor) { + let methods = []; + +// eslint-disable-next-line compat/compat + return new Proxy({}, { + get: (targetTop, name) => { + methods.push(name); + + return (() => { + // eslint-disable-next-line compat/compat + const oproxy = new Proxy(executor, { + get: (target, fnName) => { + methods.push(fnName); + return oproxy; + }, + apply: (target, ctx, args) => { + const methodsPrams = [].concat(methods); + methods = []; + + return target(methodsPrams.join('.'), args); + } + }); + + return oproxy; + })(); + } + }); +} + +module.exports = CallChain; diff --git a/2019/Jun/Week3/call-chain.test.js b/2019/Jun/Week3/call-chain.test.js new file mode 100644 index 0000000..c7f3968 --- /dev/null +++ b/2019/Jun/Week3/call-chain.test.js @@ -0,0 +1,51 @@ +const { expect } = require('chai'); +const { spy } = require('sinon'); +const CallChain = require('./call-chain'); + +describe('2019 Jun Week3 Test: call-chain', () => { + it('single call with chain', async () => { + const cc = new CallChain((method, args) => { + expect(method).to.be.eql('a.b.c'); + expect(args).to.be.an('array'); + expect(args).to.be.eql([1, 2, 3]); + }); + + await cc.a.b.c(1, 2, 3); + }); + + it('single call with no chain should meet error', async () => { + const cc = new CallChain(); + expect(() => cc()).to.throw(TypeError); + }); + + it('multiple call with chain', async () => { + const cc = new CallChain((method, args) => { + expect(method).to.be.eql('a.b.c'); + expect(args).to.be.an('array'); + expect(args).to.be.eql([1, 2, 3]); + }); + + await cc.a.b.c(1, 2, 3); + + try { + await cc.a.b(); + } catch (e) { + expect(() => { throw e }).to.throw('expected \'a.b\' to deeply equal \'a.b.c\''); + } + }); + + it('multiple call with chain use spy to detect', async () => { + const cspy = spy() + const cc = new CallChain(cspy); + + cc.a.b.c(1, 2, 3); + cc.a.b(1, 2); + + expect(cspy.called).to.be.true; + expect(cspy.callCount).to.be.equal(2); + expect(cspy.getCall(0).args[0]).to.be.equal('a.b.c'); + expect(cspy.getCall(0).args[1]).to.be.eql([1, 2, 3]); + expect(cspy.getCall(1).args[0]).to.be.equal('a.b'); + expect(cspy.getCall(1).args[1]).to.be.eql([1, 2]); + }); +}); diff --git a/package.json b/package.json index 50a5b6d..18774fb 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "good good practice, week week up.", "scripts": { "lint": "eslint --ext .js ./", - "test": "mocha **/*.test.js" + "test": "mocha './{,!(node_modules)/**}/*.test.js'" }, "repository": { "type": "git", @@ -24,7 +24,8 @@ "eslint-plugin-compat": "^3.1.1", "eslint-plugin-import": "^2.17.2", "husky": "^2.3.0", - "mocha": "^6.1.4" + "mocha": "^6.1.4", + "sinon": "^7.3.2" }, "dependencies": {}, "husky": { From 3b4ed73bc0237298111e3bb1cec02b25390d13b0 Mon Sep 17 00:00:00 2001 From: wjx <1723212606@qq.com> Date: Tue, 9 Jul 2019 00:48:45 +0800 Subject: [PATCH 12/14] 2019.07.08-week1-wjx-new --- 2019/Jul/Week1/search-index.js | 47 +++++++++++------------------ 2019/Jul/Week1/search-index.test.js | 2 +- 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/2019/Jul/Week1/search-index.js b/2019/Jul/Week1/search-index.js index eced183..3408b7b 100644 --- a/2019/Jul/Week1/search-index.js +++ b/2019/Jul/Week1/search-index.js @@ -1,17 +1,5 @@ -function intersection(a, b) { // 交集 - const result = []; - - for (let i = 0; i < b.length; i++) { - const temp = b[i]; - for (let j = 0; j < a.length; j++) { - if (temp === a[j]) { - result.push(temp); - break; - } - } - } - - return result; +function intersection(a, b) {// 交集 + return [...new Set([...new Set(a)].filter(x => new Set(b).has(x)))]; } /** @@ -28,8 +16,8 @@ module.exports = class SearchIndex { queryTokenizer: q => String(q).split(/\s+/), }, options); - this.dicts = {}; - this.identifyMaps = {}; + this.dicts = {};// 词典 + this.identifyMaps = {};// 源数据索引 } add(data) { @@ -48,33 +36,32 @@ module.exports = class SearchIndex { } search(query) { - let result = []; - const queies = this.options.queryTokenizer(query); if (queies.indexOf(query) === -1) queies.push(query); + const result = []; + let identifies = []; + queies.forEach(que => { - const r = []; + const identifiesTmp = []; - const noReatIdf = []; Object.keys(this.dicts).forEach(key => { - if (key === que || key.search(query) === 0) { + if (key === que || key.search(query) === 0) {// 匹配规则: 全等 或 前部分相等 (this.dicts[key] || []).forEach(identify => { - if (noReatIdf.indexOf(identify) === -1) { - r.push(this.identifyMaps[identify]); - noReatIdf.push(identify); - } + if (identifiesTmp.indexOf(identify) === -1) identifiesTmp.push(identify); }); } - }) + }); - if (result.length === 0) { - result = r; - } else if(r.length) { - result = intersection(result, r); + if (!identifies.length) {// identifies做交集 + identifies = identifiesTmp; + } else if (identifiesTmp.length) { + identifies = intersection(identifies, identifiesTmp); } }); + identifies.sort((a, b) => a - b).forEach(identify => result.push(this.identifyMaps[identify]));// 数字排序,字符不变 + return result; } }; diff --git a/2019/Jul/Week1/search-index.test.js b/2019/Jul/Week1/search-index.test.js index f839e15..29b650a 100644 --- a/2019/Jul/Week1/search-index.test.js +++ b/2019/Jul/Week1/search-index.test.js @@ -62,7 +62,7 @@ describe('2019 Jul Week1 Test: search-index', () => { expect(searchIndex.search('tag1')).to.be.eql([{id: 1, tags: 'tag1,tag2'}]); expect(searchIndex.search('tag2')).to.be.eql([{id: 1, tags: 'tag1,tag2'}, {id: 3, tags: 'tag2,tag5'}]); expect(searchIndex.search('tag3 tag4')).to.be.eql([{id: 2, tags: 'tag3,tag4'}]); - expect(searchIndex.search('tag')).to.be.eql([{id: 1, tags: 'tag1,tag2'}, {id: 3, tags: 'tag2,tag5'}, {id: 2, tags: 'tag3,tag4'}]); + expect(searchIndex.search('tag')).to.be.eql([{id: 1, tags: 'tag1,tag2'}, {id: 2, tags: 'tag3,tag4'}, {id: 3, tags: 'tag2,tag5'}]); expect(searchIndex.search('tagxx')).to.be.eql([]); expect(searchIndex.search('tag1 tag2 tag3')).to.be.eql([]); }); From 40cfc55ae0ba2d76948cb13f82ee8cd5b8d92cad Mon Sep 17 00:00:00 2001 From: "promise@wang" Date: Tue, 6 Aug 2019 00:15:45 +0800 Subject: [PATCH 13/14] improve --- 2019/Jul/Week5/range-map.js | 62 +++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/2019/Jul/Week5/range-map.js b/2019/Jul/Week5/range-map.js index 1801362..8504c9a 100644 --- a/2019/Jul/Week5/range-map.js +++ b/2019/Jul/Week5/range-map.js @@ -9,41 +9,43 @@ module.exports = class RangeMap { */ constructor () { - this.rangeData = [null]; - } - - resetRange(start, end, value) { - for (let i = start; i <= end; i++) { - this.rangeData[i] = value; - } + this.rangeData = []; } add(range, value) { const rangeMin = range[0]; const rangeMax = range[1]; - if (this.rangeData[rangeMin]) { - const rangeItem = this.rangeData[rangeMin]; + for (let i = 0; i < this.rangeData.length; i++) { + const rangeItem = this.rangeData[i]; + + if (rangeItem.ran[1] < rangeMin) continue; - if (rangeItem.ran[0] < rangeMin) { - this.resetRange(rangeItem.ran[0], rangeMin - 1, {ran: [rangeItem.ran[0], rangeMin - 1], val: rangeItem.val}); + if (rangeMin <= rangeItem.ran[0] && rangeMax >= rangeItem.ran[1]) { + rangeItem.deleted = true; + continue; + } + + if (rangeMin <= rangeItem.ran[0] && rangeMax < rangeItem.ran[1]) { + this.rangeData[i] = {ran: [rangeMax + 1, rangeItem.ran[1]], val: rangeItem.val}; + continue; } - } - if (this.rangeData[rangeMax]) { - const rangeItem = this.rangeData[rangeMax]; - if (rangeItem.ran[1] > rangeMax) { - this.resetRange(rangeMax + 1, rangeItem.ran[1], {ran: [rangeMax + 1, rangeItem.ran[1]], val: rangeItem.val}); + if (rangeMin > rangeItem.ran[0] && rangeMax > rangeItem.ran[1]) { + this.rangeData[i] = {ran: [rangeItem.ran[0], rangeMin - 1], val: rangeItem.val}; + continue; + } + + if (rangeMin > rangeItem.ran[0] && rangeMax < rangeItem.ran[1]) { + this.rangeData[i] = {ran: [rangeItem.ran[0], rangeMin - 1], val: rangeItem.val}; + this.rangeData.push({ran: [rangeMax + 1, rangeItem.ran[1]], val: rangeItem.val}); + break; } } - for (let i = rangeMin; i <= rangeMax; i++) { - this.rangeData[i] = { - ran: range, - val: value - }; - } - } + this.rangeData.push({ran: range, val: value}); + this.rangeData = this.rangeData.filter(rangeItem => !rangeItem.deleted); +} /** * 查找命中的区间 @@ -51,9 +53,9 @@ module.exports = class RangeMap { * @returns {array} */ findRange(search) { - if (this.rangeData[search]) { - return this.rangeData[search].ran; - } + const ri = this.rangeData.find(rangeItem => search >= rangeItem.ran[0] && search <= rangeItem.ran[1]); + + if (ri) return ri.ran; return undefined; } @@ -64,9 +66,9 @@ module.exports = class RangeMap { * @returns {any} */ findValue(search) { - if (this.rangeData[search]) { - return this.rangeData[search].val; - } + const ri = this.rangeData.find(rangeItem => search >= rangeItem.ran[0] && search <= rangeItem.ran[1]); + + if (ri) return ri.val; return undefined; } @@ -75,6 +77,6 @@ module.exports = class RangeMap { * 清空 Map */ clear() { - this.rangeData = [null]; + this.rangeData = []; } }; From ed510aaf9d28d691c5240ba40acb83ec627cfbf6 Mon Sep 17 00:00:00 2001 From: "promise@wang" Date: Sun, 11 Aug 2019 21:30:52 +0800 Subject: [PATCH 14/14] fix add (8,9,10) (1,10) but not (3,9) in test(add multiple nodes each time) --- 2019/Aug/Week2/connection-detector.js | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/2019/Aug/Week2/connection-detector.js b/2019/Aug/Week2/connection-detector.js index 7fd89be..9e9c774 100644 --- a/2019/Aug/Week2/connection-detector.js +++ b/2019/Aug/Week2/connection-detector.js @@ -1,3 +1,13 @@ +function mergeNodes(arrA, arrB) { + arrB.forEach(id => { + if (!arrA.includes(id)) { + arrA.push(id); + } + }); + + return arrA; +} + /** * 联通性检测 */ @@ -25,23 +35,22 @@ module.exports = class ConnectionDetector { identifyIDs.push(this.options.identify(node)); }); - let isInclude = false; + let newIDs = [].concat(identifyIDs); const identifySet = new Set(identifyIDs); for (let i = 0; i < this.nodeData.length; i++) { const nodeDataSet = new Set(this.nodeData[i].identifyIDs); if ((new Set([...nodeDataSet].filter(id => identifySet.has(id)))).size) { - this.nodeData[i].identifyIDs = this.nodeData[i].identifyIDs.concat(identifyIDs); - isInclude = true; - break; + this.nodeData[i].isDelete = true; + newIDs = mergeNodes(newIDs, this.nodeData[i].identifyIDs); } } - if (!isInclude) { - this.nodeData.push({ - 'identifyIDs': identifyIDs - }); - } + this.nodeData.push({ + 'identifyIDs': newIDs + }); + + this.nodeData = this.nodeData.filter(node => !node.isDelete); } /**