Skip to content

Instantly share code, notes, and snippets.

@evturn
Last active June 12, 2016 01:25
Show Gist options
  • Save evturn/be1d9b43fea2ad64021a603377a0131d to your computer and use it in GitHub Desktop.
Save evturn/be1d9b43fea2ad64021a603377a0131d to your computer and use it in GitHub Desktop.
Create Collections of Immutable Maps
class RecordMap {
set(map, record) {
if (map && !record) {
record = map
map = Immutable.Map()
}
return map.set(record.id, new Record(record))
}
setGroup(map, data) {
if (map && !data) {
data = map
map = Immutable.Map()
}
data.map(x => map = this.set(map, x))
return map
}
update(map, record, updater) {
return map.update(record.id, updater)
}
merge(maps) {
return maps.reduce((acc, x, i) => {
acc = acc.merge(x)
return acc
}, Immutable.Map())
}
delete(map, record) {
return map.delete(record.id, record)
}
clear(map) {
return map.clear()
}
}
class Record {
constructor(props) {
this.id = props.id
this.title = props.title
this.more = props.more
this.parentID = props.parentID
}
}
const data = [{
id: 1,
title: 'Call the cops',
more: 'Because someone is currently breaking into my apartment',
parentID: false
},{
id: 2,
title: 'Towels',
more: 'Get better towels.',
parentID: 8
},{
id: 3,
title: 'Drink cake',
more: 'Make sure to save some for Craig.',
parentID: 11
},{
id: 4,
title: 'Paint kitchen',
more: 'Go to a store and buy supplies',
parentID: 8
},{
id: 5,
title: 'Burgers',
more: 'Try that new place by Craig and do not invite Craig.',
parentID: 11
},{
id: 6,
title: 'Flight to Montréal',
more: 'Check your ticket.',
parentID: false
},{
id: 7,
title: 'Cables',
more: 'Surge protector.',
parentID: 8
},{
id: 8,
title: 'Household items',
more: 'Kitchen, bathroom, etc',
parentID: false
},{
id: 9,
title: 'New display',
more: '20:9 aspect ratio with rocket launchers on each side',
parentID: 8
},{
id: 10,
title: 'Salt as an entreé',
more: 'This could be good for Thanksgiving.',
parentID: 11
},{
id: 11,
title: 'Eating',
more: 'Places, even just food in general.',
parentID: false
}]
const data2 = [{
id: 12,
title: 'Call the cops',
more: 'Because someone is currently breaking into my apartment',
parentID: false
},{
id: 22,
title: 'Towels',
more: 'Get better towels.',
parentID: 8
},{
id: 32,
title: 'Drink cake',
more: 'Make sure to save some for Craig.',
parentID: 11
},{
id: 42,
title: 'Paint kitchen',
more: 'Go to a store and buy supplies',
parentID: 8
},{
id: 52,
title: 'Burgers',
more: 'Try that new place by Craig and do not invite Craig.',
parentID: 11
},{
id: 62,
title: 'Flight to Montréal',
more: 'Check your ticket.',
parentID: false
},{
id: 72,
title: 'Cables',
more: 'Surge protector.',
parentID: 8
},{
id: 82,
title: 'Household items',
more: 'Kitchen, bathroom, etc',
parentID: false
},{
id: 92,
title: 'New display',
more: '20:9 aspect ratio with rocket launchers on each side',
parentID: 8
},{
id: 102,
title: 'Salt as an entreé',
more: 'This could be good for Thanksgiving.',
parentID: 11
},{
id: 112,
title: 'Eating',
more: 'Places, even just food in general.',
parentID: false
}]
const map = new RecordMap();
const map1 = map.setGroup(data)
const map2 = map.setGroup(data2)
const map3 = map.set({
id: 201,
title: 'Chicken nuggets',
more: 'With bbq sauce'
})
console.log(map3.get(201))
/*
* [object Object] {
* id: 201,
* more: "With bbq sauce",
* parentID: undefined,
* title: "Chicken nuggets"
* }
*/
const map4 = map1.merge(map2)
const map5 = map.set({
id: 201,
title: 'Turkey nuggets',
more: 'Maybe no.'
})
console.log(map5.get(201))
/*
* [object Object] {
* id: 201,
* more: "Maybe no.",
* parentID: undefined,
* title: "Turkey nuggets"
* }
*/
map.update(map5, map5.get(201), x => {
x.title = 'Hi I completely changed your title'
return x
})
console.log(map5.get(201))
/*
* [object Object] {
* id: 201,
* more: "Maybe no.",
* parentID: undefined,
* title: "Hi I completely changed your title"
* }
*/
map.update(map3, map3.get(201), x => {
x.title = map5.get(201).title
return x
})
console.log(map3.get(201))
/*
* [object Object] {
* id: 201,
* more: "With bbq sauce",
* parentID: undefined,
* title: "Hi I completely changed your title"
* }
*/
const map6 = map.merge([map1, map2, map5])
const map7 = map.merge([map1, map2, map3, map5])
const map8 = map.set(map7, {
id: 300,
title: 'Cool stuff',
more: 'To be determined'
})
console.log(map7.get(300))
// undefined
console.log(map8.get(300))
/*
* [object Object] {
* id: 300,
* more: "To be determined",
* parentID: undefined,
* title: "Cool stuff"
* }
*/
console.log(map1.size)
// 11
console.log(map2.size)
// 11
console.log(map3.size)
// 1
console.log(map4.size)
// 22
console.log(map5.size)
// 1
console.log(map6.size)
// 23
console.log(map7.size)
// 23
console.log(map8.size)
// 24
const { OrderedMap } = Immutable
const initialState = __INITIAL_STATE__
function createMap(data) {
return data
.filter(hasNoParents)
.map(x => ({ ...x, kids: data.filter(filterKids(x))}))
.map(x => ({ ...x, kids: setKids(x) }))
.reduce(reduceToMap, OrderedMap())
}
const hasNoParents = x => !x.parentID
const reduceToMap = (acc, x) => (
acc = acc.set(x.id, x)
)
const filterKids = x => (
x2 => x2.parentID == x.id
)
const setKids = ({ kids }) => (
kids.length ? kids.reduce(reduceToMap, OrderedMap()) : false
)
const map = createMap(initialState)
console.log(initialState.length)
// 11
console.log(map.size)
// 4
console.log(map.get(8).kids.size)
// 4
console.log(map.get(11).kids.size)
// 3
console.log(map.toJS())
/*
* [object Object] {
* 1: [object Object] {
* id: 1,
* kids: false,
* more: "Because someone is currently breaking into my apartment",
* parentID: false,
* title: "Call the cops"
* },
* 11: [object Object] {
* id: 11,
* kids: [object Object] { ... },
* more: "Places, even just food in general.",
* parentID: false,
* title: "Eating"
* },
* 6: [object Object] {
* id: 6,
* kids: false,
* more: "Check your ticket.",
* parentID: false,
* title: "Flight to Montréal"
* },
* 8: [object Object] {
* id: 8,
* kids: [object Object] { ... },
* more: "Kitchen, bathroom, etc",
* parentID: false,
* title: "Household items"
* }
* }
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment