From e3e7cd30030384109f7936a134e8ffc6e126bc0c Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Wed, 5 Feb 2020 10:32:20 -0500 Subject: [PATCH] Memoize `presetCollection.item` (it's an Array.find) Also add tests for `matchAllGeometry` --- modules/presets/collection.js | 28 ++++++++++++++++++---------- modules/presets/index.js | 6 ++++-- modules/presets/preset.js | 4 +--- test/spec/presets/preset.js | 12 ++++++++++++ 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/modules/presets/collection.js b/modules/presets/collection.js index 62cefa24e..dd1b56021 100644 --- a/modules/presets/collection.js +++ b/modules/presets/collection.js @@ -1,14 +1,23 @@ import { utilArrayUniq, utilEditDistance } from '../util'; +// +// `presetCollection` is a wrapper around an `Array` of presets `collection`, +// and decorated with some extra methods for searching and matching geometry +// export function presetCollection(collection) { const MAXRESULTS = 50; - let _this = {}; + let _memo = {}; _this.collection = collection; - _this.item = (id) => _this.collection.find(d => d.id === id); + _this.item = (id) => { + if (_memo[id]) return _memo[id]; + const found = _this.collection.find(d => d.id === id); + if (found) _memo[id] = found; + return found; + }; _this.index = (id) => _this.collection.findIndex(d => d.id === id); @@ -19,16 +28,15 @@ export function presetCollection(collection) { }; _this.matchAllGeometry = (geometries) => { - return presetCollection(_this.collection.filter(d => { - if (!d) return false; - return d.matchAllGeometry(geometries); - })); + return presetCollection( + _this.collection.filter(d => d && d.matchAllGeometry(geometries)) + ); }; _this.matchAnyGeometry = (geometries) => { - return presetCollection(_this.collection.filter(d => { - return geometries.some(geom => d.matchGeometry(geom)); - })); + return presetCollection( + _this.collection.filter(d => geometries.some(geom => d.matchGeometry(geom))) + ); }; _this.fallback = (geometry) => { @@ -38,7 +46,7 @@ export function presetCollection(collection) { }; _this.search = (value, geometry, countryCode) => { - if (!value) return this; + if (!value) return _this; value = value.toLowerCase().trim(); diff --git a/modules/presets/index.js b/modules/presets/index.js index 213dfd544..519439f06 100644 --- a/modules/presets/index.js +++ b/modules/presets/index.js @@ -15,8 +15,10 @@ export { presetField }; export { presetPreset }; -// wraps a presetCollection with methods for -// loading new data and returning defaults +// +// `presetIndex` wraps a `presetCollection` +// with methods for loading new data and returning defaults +// export function presetIndex(context) { const dispatch = d3_dispatch('recentsChange'); const MAXRECENTS = 30; diff --git a/modules/presets/preset.js b/modules/presets/preset.js index 02c6fb598..cb8e28800 100644 --- a/modules/presets/preset.js +++ b/modules/presets/preset.js @@ -95,9 +95,7 @@ export function presetPreset(presetID, preset, fields, addable, rawPresets) { _this.matchGeometry = (geom) => _this.geometry.indexOf(geom) >= 0; - _this.matchAllGeometry = (geometries) => { - return geometries.every(geom => _this.geometry.indexOf(geom) >= 0); - }; + _this.matchAllGeometry = (geoms) => geoms.every(_this.matchGeometry); _this.originalScore = _this.matchScore || 1; diff --git a/test/spec/presets/preset.js b/test/spec/presets/preset.js index c16054b1b..e18f03131 100644 --- a/test/spec/presets/preset.js +++ b/test/spec/presets/preset.js @@ -16,6 +16,18 @@ describe('iD.presetPreset', function() { }); }); + describe('#matchAllGeometry', function() { + it('returns false if they don\'t all match', function() { + var preset = iD.presetPreset('test', {geometry: ['line']}); + expect(preset.matchAllGeometry(['point','line'])).to.equal(false); + }); + + it('returns true if they do all match', function() { + var preset = iD.presetPreset('test', {geometry: ['point', 'line']}); + expect(preset.matchAllGeometry(['point','line'])).to.equal(true); + }); + }); + describe('#matchScore', function() { it('returns -1 if preset does not match tags', function() { var preset = iD.presetPreset('test', {tags: {foo: 'bar'}});