commit 90c3a2a08329d8f37cd25657f4432d728ce683be Author: Sven Slootweg Date: Fri Feb 21 20:56:34 2020 +0100 Initial commit; v1.0.0 diff --git a/README.md b/README.md new file mode 100644 index 0000000..11254cf --- /dev/null +++ b/README.md @@ -0,0 +1,68 @@ +# generate-lookup-table + +Generates a (fast!) lookup table or index from any array of items. + +__When to use this:__ When you might otherwise be looping through an array *many times* (eg. using `Array#find`), trying to locate an item(s) with a particular property. + +If you'd otherwise only loop through the array *once*, it's probably faster *not* to use this library, and just do the loop - building a lookup table, while still quite fast in the bigger picture, takes time. + +## License, donations, and other boilerplate + +Licensed under either the [WTFPL](http://www.wtfpl.net/txt/copying/) or [CC0](https://creativecommons.org/publicdomain/zero/1.0/), at your choice. In practice, that means it's more or less public domain, and you can do whatever you want with it. Giving credit is *not* required, but still very much appreciated! I'd love to [hear from you](mailto:admin@cryto.net) if this module was useful to you. + +Creating and maintaining open-source modules is a lot of work. A donation is also not required, but much appreciated! You can donate [here](http://cryto.net/~joepie91/donate.html). + +## Usage + +```js +"use strict"; + +const generateLookupTable = require("generate-lookup-table"); + +// Thanks to https://gist.github.com/nanotaboada/6396437 for the sample data! + +let items = [ + { name: "Eloquent JavaScript, Second Edition", tags: [ "javascript", "No Starch Press" ] }, + { name: "Learning JavaScript Design Patterns", tags: [ "javascript", "O'Reilly Media" ] }, + { name: "Speaking JavaScript", tags: [ "javascript", "O'Reilly Media" ] }, + { name: "Programming JavaScript Applications", tags: [ "javascript", "O'Reilly Media" ] }, + { name: "Understanding ECMAScript 6", tags: [ "javascript", "No Starch Press" ] }, + { name: "You Don't Know JS", tags: [ "javascript", "O'Reilly Media" ] }, + { name: "Git Pocket Guide", tags: [ "git", "O'Reilly Media" ] }, + { name: "Designing Evolvable Web APIs with ASP.NET", tags: [ "asp.net", "O'Reilly Media" ] }, +]; + +let lookupTable = generateLookupTable(items, (item) => item.tags); + +console.log(lookupTable.get("git")); + +/* Output: + [ { name: 'Git Pocket Guide', tags: [ 'git', 'O\'Reilly Media' ] } ] +*/ + +console.log(lookupTable.get("No Starch Press")); + +/* Output: + [ { name: 'Eloquent JavaScript, Second Edition', + tags: [ 'javascript', 'No Starch Press' ] }, + { name: 'Understanding ECMAScript 6', + tags: [ 'javascript', 'No Starch Press' ] } ] +*/ +``` + +## API + +### generateLookupTable(items, keyFunction) + +Generates a lookup table for the given set of `items`, using the `keyFunction` to determine what key(s) each item should be registered for. + +- __items:__ The array of items to index. +- __keyFunction(item):__ A function that, given an `item` as its argument, returns the key(s) for that item. The function may return either a single key, an array of them, or nothing at all. + +Returns a `Map` that maps from a key (as returned from the `keyFunction`) to all items that returned that particular key. + +## Changelog + +### v1.0.0 (February 21, 2020) + +Initial release. diff --git a/example.js b/example.js new file mode 100644 index 0000000..6f765b6 --- /dev/null +++ b/example.js @@ -0,0 +1,33 @@ +"use strict"; + +const generateLookupTable = require("./"); + +// Thanks to https://gist.github.com/nanotaboada/6396437 for the sample data! + +let items = [ + { name: "Eloquent JavaScript, Second Edition", tags: [ "javascript", "No Starch Press" ] }, + { name: "Learning JavaScript Design Patterns", tags: [ "javascript", "O'Reilly Media" ] }, + { name: "Speaking JavaScript", tags: [ "javascript", "O'Reilly Media" ] }, + { name: "Programming JavaScript Applications", tags: [ "javascript", "O'Reilly Media" ] }, + { name: "Understanding ECMAScript 6", tags: [ "javascript", "No Starch Press" ] }, + { name: "You Don't Know JS", tags: [ "javascript", "O'Reilly Media" ] }, + { name: "Git Pocket Guide", tags: [ "git", "O'Reilly Media" ] }, + { name: "Designing Evolvable Web APIs with ASP.NET", tags: [ "asp.net", "O'Reilly Media" ] }, +]; + +let lookupTable = generateLookupTable(items, (item) => item.tags); + +console.log(lookupTable.get("git")); + +/* Output: + [ { name: 'Git Pocket Guide', tags: [ 'git', 'O\'Reilly Media' ] } ] +*/ + +console.log(lookupTable.get("No Starch Press")); + +/* Output: + [ { name: 'Eloquent JavaScript, Second Edition', + tags: [ 'javascript', 'No Starch Press' ] }, + { name: 'Understanding ECMAScript 6', + tags: [ 'javascript', 'No Starch Press' ] } ] +*/ diff --git a/index.js b/index.js new file mode 100644 index 0000000..1fb82dc --- /dev/null +++ b/index.js @@ -0,0 +1,31 @@ +"use strict"; + +module.exports = function generateLookupTable(items, getKey) { + let lookupTable = new Map(); + + function setItem(key, value) { + // TODO: Add a fast path for unique keys (no array wrapping), so that the index can contain both single items and arrays? + if (lookupTable.has(key)) { + lookupTable.get(key).push(value); + } else { + lookupTable.set(key, [ value ]); + } + } + + items.forEach((item) => { + let key = getKey(item); + + if (key != null) { + if (Array.isArray(key)) { + // This item should be available under multiple keys + for (let keyItem of key) { + setItem(keyItem, item); + } + } else { + setItem(key, item); + } + } + }); + + return lookupTable; +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..b263003 --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "name": "generate-lookup-table", + "description": "Generates a (fast!) lookup table or index from any array of items.", + "keywords": [ "index", "lookup table", "map", "generate", "generator" ], + "version": "1.0.0", + "main": "index.js", + "repository": "https://git.cryto.net/joepie91/generate-lookup-table.git", + "author": "Sven Slootweg ", + "license": "WTFPL OR CC0-1.0" +}