UNPKG

theprogrammablemind

Version:

129 lines (115 loc) 3.04 kB
const _ = require('lodash') const deepEqual = require('deep-equal') const groupBy = (property, list) => { const groups = {} for (const element of list) { if (!groups[element[property]]) { groups[element[property]] = [] } groups[element[property]].push(element) } return groups } const toList = (value) => { if (value.marker === 'list') { return value } else { return { marker: 'list', types: Array.from(new Set((value.types || []).concat(['list', value.marker]))), value: [value] } } } const concatLists = (l1, l2) => { l1 = toList(l1) l2 = toList(l2) return { marker: 'list', types: Array.from(new Set(l1.types.concat(l2.types))), value: Array.from(new Set(l1.value.concat(l2.value))) } } const findPropertyWithManyValues = (contexts, properties) => { for (const property of properties) { if (new Set(contexts.map((context) => context[property])).size == 1) { return property } } } /* class JSONSet { constructor(list = []) { this.members = [] for (const element of list) { this.add(element) } } toList(element) { return this.list } add(element) { if (!this.has(element)) { this.list.push(element) } } has(searchFor) { for (const element of this.list) { if (!deepEqual(searchFor, element) { return true } } return false } } */ // x want y and z OR A // x and y want z B // x wants and likes y C const canonicalDefault = (value) => { if (!value || !value.marker) { return value } return { marker: value.marker, value: value.value, word: value.wordi, types: value.types } } // if properties null then check the contexts for unflatten property const unflatten = (contexts, properties, canonical = canonicalDefault) => { const grouped = {} for (const context of contexts) { if (!grouped[context.marker]) { grouped[context.marker] = [] } grouped[context.marker].push(context) } let results = [] for (const key in grouped) { results = results.concat(unflattenHelper(grouped[key], properties || grouped[key][0].unflatten, canonical)) } return results } // properties -> order of preference for grouping values, for example B,A,c const unflattenHelper = (contexts, properties, canonical) => { if (contexts.length < 2) { return contexts } if (!properties) { return contexts } const groupedByMarker = groupBy('marker', contexts) const unflats = [] for (const key in groupedByMarker) { const grouping = groupedByMarker[key] const groupingProp = findPropertyWithManyValues(contexts, properties) const first = _.cloneDeep(grouping[0]) for (const next of grouping.slice(1)) { for (const prop in next) { if (!deepEqual(canonical(next[prop]), canonical(first[prop]))) { first[prop] = concatLists(first[prop], next[prop]) } } } unflats.push(first) } return unflats } module.exports = { groupBy, unflatten }