Created
June 9, 2016 21:20
-
-
Save austinzheng/65dcbb69aac304b0418b261bfe24410b to your computer and use it in GitHub Desktop.
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
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