Created
April 19, 2016 18:06
-
-
Save TheSeamau5/7aa631a77c31f79467c1f16374f74f78 to your computer and use it in GitHub Desktop.
Selection List in Javascript using Immutable
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
import Immutable from 'immutable'; | |
/* Selection List Data Structure */ | |
class SelectionList { | |
constructor(list) { | |
if (list.length > 0) { | |
this._previous = new Immutable.Stack(); | |
this._selected = list[0]; | |
this._next = new Immutable.Stack(list.splice(1)); | |
} else { | |
throw new Error('Selection list must include at least one element'); | |
} | |
} | |
toArray() { | |
return this._previous.toSeq() | |
.reverse() | |
.toArray() | |
.concat(this._selected) | |
.concat(this._next.toSeq().toArray()); | |
} | |
map(f) { | |
const previousSize = this._previous.size; | |
const previous = new Immutable.Stack(this._previous.toSeq().reverse().map(f).reverse()); | |
const selected = f(this._selected, previousSize); | |
const next = new Immutable.Stack(this._next.toArray().map((x, index) => f(x, index + previousSize + 1))); | |
return makeSelectionList(previous, selected, next); | |
} | |
next() { | |
if (this._next.size > 0) { | |
const previous = this._previous.push(this._selected); | |
const selected = this._next.peek(); | |
const next = this._next.pop(); | |
return makeSelectionList(previous, selected, next); | |
} else { | |
return this; | |
} | |
} | |
previous() { | |
if (this._previous.size > 0) { | |
const selected = this._previous.peek(); | |
const previous = this._previous.pop(); | |
const next = this._next.push(this._selected); | |
return makeSelectionList(previous, selected, next); | |
} else { | |
return this; | |
} | |
} | |
get selectedIndex() { | |
return this._previous.size; | |
} | |
goto(index) { | |
const currentIndex = this.selectedIndex; | |
if (index === currentIndex) { | |
return this; | |
} else if (currentIndex < index && this._next.size > 0) { | |
return this.next().goto(index); | |
} else if (currentIndex > Math.max(0, index)) { | |
return this.previous().goto(index); | |
} else { | |
return this; | |
} | |
} | |
toObject() { | |
return { | |
previous: this._previous.toArray(), | |
selected: this._selected, | |
next: this._next.toArray() | |
}; | |
} | |
updateSelected(f) { | |
return makeSelectionList( | |
this._previous, | |
f(this._selected), | |
this._next | |
); | |
} | |
} | |
const SelectionListPrototype = SelectionList.prototype; | |
const makeSelectionList = (previous, selected, next) => { | |
let selectionList = Object.create(SelectionListPrototype); | |
selectionList._previous = previous; | |
selectionList._selected = selected; | |
selectionList._next = next; | |
return selectionList; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment