Skip to content

Instantly share code, notes, and snippets.

@austinzheng
Created June 9, 2016 21:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save austinzheng/65dcbb69aac304b0418b261bfe24410b to your computer and use it in GitHub Desktop.
Save austinzheng/65dcbb69aac304b0418b261bfe24410b to your computer and use it in GitHub Desktop.
struct StringTupleCollection : Collection {
let backing : [String : [String]]
var startIndex : StringTupleIndex {
// Find the first key with a non-empty array
var idx = backing.startIndex
while idx != backing.endIndex {
let array = backing[idx].1
if !array.isEmpty {
return StringTupleIndex(dictKey: idx, arrayKey: 0)
} else {
idx = backing.index(after: idx)
}
}
return StringTupleIndex(dictKey: backing.startIndex, arrayKey: 0)
}
var endIndex : StringTupleIndex {
var idx = backing.startIndex
var prevValidIdx : DictionaryIndex<String, [String]>?
// TODO: make this not awful
while idx != backing.endIndex {
if backing[idx].1.count > 0 {
prevValidIdx = idx
}
idx = backing.index(after: idx)
}
if let prevValidIdx = prevValidIdx {
return StringTupleIndex(dictKey: prevValidIdx, arrayKey: backing[prevValidIdx].1.count)
} else {
return startIndex
}
}
func index(after i: StringTupleIndex) -> StringTupleIndex {
let dictKey = i.dictKey
let arrayKey = i.arrayKey
let array = backing[dictKey].1
if arrayKey < array.count - 1 {
// Same array
return StringTupleIndex(dictKey: dictKey, arrayKey: arrayKey + 1)
} else {
// Next dict
var nextKey = backing.index(after: dictKey)
while nextKey != backing.endIndex {
// Does this key have an array?
let thisArray = backing[nextKey].1
if !thisArray.isEmpty {
return StringTupleIndex(dictKey: nextKey, arrayKey: 0)
}
nextKey = backing.index(after: nextKey)
}
return endIndex
}
}
subscript(i: StringTupleIndex) -> (String, String) {
let array = backing[i.dictKey]
return (array.0, array.1[i.arrayKey])
}
init(_ backing: [String : [String]]) {
self.backing = backing
}
}
struct StringTupleIndex : Comparable {
let dictKey : Dictionary<String, [String]>.Index
let arrayKey : Array<String>.Index
}
func ==(lhs: StringTupleIndex, rhs: StringTupleIndex) -> Bool {
return lhs.dictKey == rhs.dictKey && lhs.arrayKey == rhs.arrayKey
}
func <(lhs: StringTupleIndex, rhs: StringTupleIndex) -> Bool {
if lhs.dictKey < rhs.dictKey {
return true
} else if lhs.dictKey > rhs.dictKey {
return false
} else {
return lhs.arrayKey < rhs.arrayKey
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment