Object Array Transposer(y) - JS objects with multiple key/value structures
The idea (j-m's) was to find a way of being able to get values from an array of objects in O(1) time, in an environment where memory isn't an issue.
For example, I could have the following JS object:
const food = [
{
id: 1,
name: "apple",
type: "fruit",
},
{
id: 2,
name: "orange",
type: "fruit",
},
{
id: 3,
name: "broccoli",
type: "vegetable",
},
];As-is, to get the item where the id is 3, I'd use food.find(x => x.id === 3) or similar.
If the array was transposed to use id as object keys, the resultant object would look like the following:
const foodById = {
1: {
id: 1,
name: "apple",
type: "fruit",
},
2: {
id: 2,
name: "orange",
type: "fruit",
},
3: {
id: 3,
name: "broccoli",
type: "vegetable",
},
};This way, we can get the food with the id of 3 with foodById[3].
However, we don't know that object keys will all be unique, so objects should be placed in arrays. For example:
const foodByType = {
fruit: [
{
id: 1,
name: "apple",
type: "fruit",
},
{
id: 2,
name: "orange",
type: "fruit",
},
],
vegetable: [
{
id: 3,
name: "broccoli",
type: "vegetable",
},
],
};Now, to get an array of fruit, rather than using food.filter(f => f.type === 'fruit') we can just use foodByType['fruit'].
For data that changes frequently, this is a bad approach since transposing the data to use different key values is expensive.
However, for data that is assigned once (e.g. when a server first starts running) or assigned relatively infrequently (e.g. polling a database) this idea should be far less CPU-intensive than frequently searching the array using filter, find, or manually.
This library's default export is OatyArray. Initialise it as such:
const oatyFood = new OatyArray(food, { keys: ["id", "type"] });In the above case, food is the initial array of items and ['id', 'type'] is the array of keys you want to be able to query.
The OatyArray constructor generates the transposed caches.
To query data, use the get method:
const fruitArray = oatyFood.get("type", "fruit");The above is effectively the same as foodByType['fruit'] in the above examples
oaty is built with Typescript
To get started, run npm install to install dependencies.
- Run tests:
npm test - Build:
npm run build
Feel free to open Issues/PRs with suggestions/problems/improvements.
Library is versioned as-per the semver standard.
- Added extra type inference and enforcement to Oaty, this means that an array can be initialised
new OatyArray([{ myKey: "myValue" }])without needing to provide a type. keysinput is now enforced to a subset of the keys of the given typekeysinput will now be used to enforce that only valid objects are transposed by Oaty.keyswill now always return either an array containing all the auto transposed keys, or an array of the configured keys, and is now type correct.- Oaty will now enforce the correct keys are the objects of
.pushmeaning that an error will be thrown at compile time if an invalid object is being passed to Oaty. - Updated overloads on
.getto return the correct types depending on usage - Updated to
[email protected] - Added
tsdtests
- Oaty can now be initialised with
new OatyArray<T>()so that.get,.data, and.transposedreturn data of typeT. This is completely optional asTdefaults toany. - Removed
missingKeyReturnsandnoResultsReturnsoptions. - Exported a new type for the
_transposedproperty. - Expanded the ternary conditions to improve readability.
- Made the
dataconstructor param optional and default to[]. - When a key is not transposed and
.getsearches for that key, it will now throw aReferenceError. - Added NYC and increased tests to 100% coverage.
- Added
gets fordata,keys, andtransposed - Made
keysoptional - will transpose every (root) key in an object - Added two options to change the return value for when they key or value of
.get()is undefined - Renamed
originaltodata .get()can now retrieve all objects that have a key, like.get('fruit')- Added simple benchmark
- Added more tests
- Fixed
.get()method type (object[])
- Renamed
OatyObjecttoOatyArray, since it's intended as an array alternative, rather than an object alternative - Named export, rather than default export
- Added
.pushfunction
- Initial proof of concept