Last active
January 4, 2018 17:57
-
-
Save ifyoumakeit/20e47b4bb413ffd610546b25125fe5ae to your computer and use it in GitHub Desktop.
Sortable Data Access Structure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Sort or set keys | |
* @param data {object} Keyed data store | |
* @param keysOrSort {array|function} | |
* @return {array} | |
*/ | |
const sortKeys = (data, keysOrSort) => { | |
return typeof keysOrSort === "undefined" | |
? Object.keys(data).sort() | |
: typeof keysOrSort === "function" | |
? Object.keys(data).sort((keyA, keyB) => { | |
return keysOrSort( | |
{ key: keyA, data: data[keyA] }, | |
{ key: keyB, data: data[keyB] } | |
); | |
}) | |
: typeof keysOrSort === "object" ? keysOrSort : [keysOrSort]; | |
}; | |
/** | |
* Remove data that isn't in keys. | |
* @param data {object} Keyed data store | |
* @param keys {array} Sorted data keys | |
*/ | |
const cleanData = (data, keys) => { | |
return keys.reduce( | |
(memo, key) => (data[key] ? { ...memo, [key]: data[key] } : memo), | |
{} | |
); | |
}; | |
/** | |
* Sortable data access object. | |
* Array/Object methods are remapped to support both. | |
* @param {object} Keyed data store | |
* @param {array|function} keysOrSort Sorted array of object keys or sorting function. | |
* @return {Struct} | |
* @example const struct1 = Struct({foo: {active: false}, bar: {active: true}}, ["foo", "bar"]) | |
* @example const struct2 = Struct({foo: {active: false}, bar: {active: true}}, (a,b) => a > b ? -1 : 1) | |
*/ | |
const Struct = function(data = {}, keysOrSort) { | |
let _keys = sortKeys(data, keysOrSort); | |
let _data = cleanData(data, _keys); | |
const values = () => { | |
return _keys.map(val => _data[val]); | |
}; | |
const keys = () => { | |
return _keys; | |
}; | |
const key = index => { | |
return _keys[index]; | |
}; | |
const get = keyOrIndex => { | |
return typeof keyOrIndex === "number" | |
? data[_keys[keyOrIndex]] || {} | |
: _data[keyOrIndex] || {}; | |
}; | |
const set = (key, value) => { | |
return Struct({ ..._data, [key]: _keys.concat(key) }); | |
}; | |
const has = key => { | |
return typeof _data[key] !== "undefined"; | |
}; | |
const sort = callback => { | |
return _keys.sort(callback).map(key => _data[key]); | |
}; | |
const forEach = callback => { | |
return _keys.forEach((key, index) => { | |
return callback(_data[key], index, _data); | |
}); | |
}; | |
const map = callback => { | |
const data = {}; | |
_keys.forEach((key, index) => { | |
data[key] = callback(_data[key], index, _data); | |
}); | |
return Struct(data, _keys); | |
}; | |
const filter = callback => { | |
const data = {}; | |
let keys = []; | |
_keys.forEach((key, index) => { | |
if (callback(_data[key], index, _data)) { | |
data[key] = _data[key]; | |
keys = keys.concat(key); | |
} | |
}); | |
return Struct(data, keys); | |
}; | |
const reduce = (callback, initialValue) => { | |
return _keys.reduce((memo, key, index) => { | |
return callback(memo, _data[key], index, _data); | |
}, initialValue); | |
}; | |
return { | |
has, | |
key, | |
keys, | |
values, | |
get, | |
set, | |
sort, | |
forEach, | |
map, | |
filter, | |
reduce | |
}; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const cryptids = Struct( | |
{ | |
kevin: { | |
name: "Kevin Pruett", | |
pets: 1 | |
}, | |
dave: { | |
name: "Dave Garwacke", | |
pets: 2 | |
}, | |
andy: { | |
name: "Andy Fritz", | |
pets: 0 | |
}, | |
molly: { | |
name: "Molly McGrath", | |
pets: 0.5 | |
} | |
}, | |
({ data: a }, { data: b }) => (a.name > b.name ? 1 : -1) | |
); | |
console.log({ | |
hasTodd: cryptids.has("todd"), | |
sortedKeys: cryptids.keys(), | |
thirdKey: cryptids.key(2), | |
withCounts: cryptids.map(c => ({ ...c, count: c.pets + 1 })).values(), | |
cryptids: cryptids.set("tatonka", { name: "Tatonka", pets: 0 }).values(), | |
petOwners: cryptids.filter(c => c.pets >= 1).values() | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment