Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9074b8abe8 | |||
| 7f58e9ae8d | |||
| feffcd9041 | |||
| e963b30ff8 | |||
| 23725866ab | |||
| 9aa12bb2aa | |||
| 4bcf559767 |
@@ -11,7 +11,7 @@ Internally `OrderedDictionary` uses a backing store composed of an instance of `
|
||||
## Requirements
|
||||
|
||||
- Swift 2.0
|
||||
- Xcode 7.0 beta 6+
|
||||
- Xcode 7.0 GM
|
||||
- iOS 8.0+ / OS X 10.10+
|
||||
|
||||
## Installation
|
||||
@@ -19,7 +19,7 @@ Internally `OrderedDictionary` uses a backing store composed of an instance of `
|
||||
The easiest way to integrate `OrderedDictionary` to your project is to use [Carthage][6]. Add following line to your `Cartfile`:
|
||||
|
||||
```
|
||||
github "lukaskubanek/OrderedDictionary" ~> 0.1
|
||||
github "lukaskubanek/OrderedDictionary" ~> 0.3
|
||||
```
|
||||
|
||||
Then drag the `OrderedDictionary.xcodeproj` or the `OrderedDictionary.framework` into your project/workspace and link against the `OrderedDictionary.framework`.
|
||||
@@ -120,7 +120,7 @@ Lukas Kubanek // [lukaskubanek.com][11] // [@kubanekl][12]
|
||||
|
||||
[image-1]: https://img.shields.io/travis/lukaskubanek/OrderedDictionary.svg?style=flat-square
|
||||
[image-2]: https://img.shields.io/github/release/lukaskubanek/OrderedDictionary.svg?style=flat-square
|
||||
[image-3]: https://img.shields.io/badge/Swift-2.0_(7b6)-orange.svg?style=flat-square
|
||||
[image-3]: https://img.shields.io/badge/Swift-2.0-orange.svg?style=flat-square
|
||||
[image-4]: https://img.shields.io/badge/platform-OS_X%20&_iOS-yellowgreen.svg?style=flat-square
|
||||
[image-5]: https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat-square "Carthage compatible"
|
||||
[image-6]: https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat-square "License"
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
// Copyright © 2015 Lukas Kubanek. All rights reserved.
|
||||
//
|
||||
|
||||
/// The `OrderedDictionary` is a collection which combines the features of `Dictionary` and `Array`.
|
||||
/// It maps keys to values and additionally sorts the key-value pairs by zero-based integer index.
|
||||
public struct OrderedDictionary<Key: Hashable, Value>: CollectionType, ArrayLiteralConvertible, CustomStringConvertible {
|
||||
|
||||
// MARK: - Initialization
|
||||
@@ -55,21 +53,30 @@ public struct OrderedDictionary<Key: Hashable, Value>: CollectionType, ArrayLite
|
||||
|
||||
public mutating func updateValue(value: Value, forKey key: Key) -> Value? {
|
||||
if orderedKeys.contains(key) {
|
||||
guard let currentValue = keysToValues[key] else { fatalError("Inconsistency error occured in OrderedDictionary.") }
|
||||
guard let currentValue = keysToValues[key] else {
|
||||
fatalError("Inconsistency error occured in OrderedDictionary")
|
||||
}
|
||||
|
||||
keysToValues[key] = value
|
||||
|
||||
return currentValue
|
||||
} else {
|
||||
orderedKeys.append(key)
|
||||
keysToValues[key] = value
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public mutating func removeValueForKey(key: Key) -> Value? {
|
||||
if let index = orderedKeys.indexOf(key) {
|
||||
guard let currentValue = keysToValues[key] else {
|
||||
fatalError("Inconsistency error occured in OrderedDictionary")
|
||||
}
|
||||
|
||||
orderedKeys.removeAtIndex(index)
|
||||
guard let currentValue = keysToValues[key] else { fatalError("Inconsistency error occured in OrderedDictionary.") }
|
||||
keysToValues[key] = nil
|
||||
|
||||
return currentValue
|
||||
} else {
|
||||
return nil
|
||||
@@ -85,11 +92,11 @@ public struct OrderedDictionary<Key: Hashable, Value>: CollectionType, ArrayLite
|
||||
|
||||
public subscript(index: Index) -> Element {
|
||||
get {
|
||||
if let element = elementAtIndex(index) {
|
||||
return element
|
||||
} else {
|
||||
fatalError("Index out of bounds in OrderedDictionary.")
|
||||
guard let element = elementAtIndex(index) else {
|
||||
fatalError("OrderedDictionary index out of range")
|
||||
}
|
||||
|
||||
return element
|
||||
}
|
||||
set(newValue) {
|
||||
updateElement(newValue, atIndex: index)
|
||||
@@ -104,21 +111,52 @@ public struct OrderedDictionary<Key: Hashable, Value>: CollectionType, ArrayLite
|
||||
guard orderedKeys.indices.contains(index) else { return nil }
|
||||
|
||||
let key = orderedKeys[index]
|
||||
guard let value = self.keysToValues[key] else { fatalError("Inconsistency error occured in OrderedDictionary.") }
|
||||
|
||||
guard let value = self.keysToValues[key] else {
|
||||
fatalError("Inconsistency error occured in OrderedDictionary")
|
||||
}
|
||||
|
||||
return (key, value)
|
||||
}
|
||||
|
||||
public mutating func insertElement(newElement: Element, atIndex index: Index) -> Value? {
|
||||
guard index >= 0 else {
|
||||
fatalError("Negative OrderedDictionary index is out of range")
|
||||
}
|
||||
|
||||
guard index <= count else {
|
||||
fatalError("OrderedDictionary index out of range")
|
||||
}
|
||||
|
||||
let (key, value) = (newElement.0, newElement.1)
|
||||
|
||||
let adjustedIndex: Int
|
||||
let currentValue: Value?
|
||||
|
||||
if let currentIndex = orderedKeys.indexOf(key) {
|
||||
currentValue = keysToValues[key]
|
||||
adjustedIndex = (currentIndex < index - 1) ? index - 1 : index
|
||||
|
||||
orderedKeys.removeAtIndex(currentIndex)
|
||||
keysToValues[key] = nil
|
||||
} else {
|
||||
currentValue = nil
|
||||
adjustedIndex = index
|
||||
}
|
||||
|
||||
orderedKeys.insert(key, atIndex: adjustedIndex)
|
||||
keysToValues[key] = value
|
||||
|
||||
return currentValue
|
||||
}
|
||||
|
||||
public mutating func updateElement(element: Element, atIndex index: Index) -> Element? {
|
||||
// TODO: Handle index out of range
|
||||
|
||||
let currentElement = elementAtIndex(index)
|
||||
|
||||
if currentElement != nil {
|
||||
keysToValues.removeValueForKey(element.0)
|
||||
guard let currentElement = elementAtIndex(index) else {
|
||||
fatalError("OrderedDictionary index out of range")
|
||||
}
|
||||
|
||||
let (newKey, newValue) = (element.0, element.1)
|
||||
|
||||
orderedKeys[index] = newKey
|
||||
keysToValues[newKey] = newValue
|
||||
|
||||
@@ -158,7 +196,11 @@ public struct OrderedDictionary<Key: Hashable, Value>: CollectionType, ArrayLite
|
||||
guard nextIndex < lastIndex else { return nil }
|
||||
|
||||
let nextKey = self.orderedKeys[nextIndex]
|
||||
guard let nextValue = self.keysToValues[nextKey] else { fatalError("Inconsistency error occured in OrderedDictionary.") }
|
||||
|
||||
guard let nextValue = self.keysToValues[nextKey] else {
|
||||
fatalError("Inconsistency error occured in OrderedDictionary")
|
||||
}
|
||||
|
||||
let element = (nextKey, nextValue)
|
||||
|
||||
nextIndex++
|
||||
|
||||
@@ -120,6 +120,67 @@ class OrderedDictionaryTests: XCTestCase {
|
||||
expect(self.orderedDictionary.elementAtIndex(10)).to(beNil())
|
||||
}
|
||||
|
||||
func testIndexBasedInsertionsOfElementsWithDistinctKeys() {
|
||||
self.orderedDictionary.insertElement(("T", 15), atIndex: 0)
|
||||
self.orderedDictionary.insertElement(("U", 16), atIndex: 2)
|
||||
self.orderedDictionary.insertElement(("V", 17), atIndex: 5)
|
||||
self.orderedDictionary.insertElement(("W", 18), atIndex: 2)
|
||||
|
||||
let expectedOrderedDictionary: OrderedDictionary<String, Int> = [
|
||||
("T", 15),
|
||||
("A", 1),
|
||||
("W", 18),
|
||||
("U", 16),
|
||||
("B", 2),
|
||||
("C", 3),
|
||||
("V", 17)
|
||||
]
|
||||
|
||||
expect(self.orderedDictionary == expectedOrderedDictionary).to(beTrue())
|
||||
}
|
||||
|
||||
func testIndexBasedInsertionOfElementWithSameKeyBeforeItsCurrentIndex() {
|
||||
let previousValue = self.orderedDictionary.insertElement(("B", 5), atIndex: 0)
|
||||
|
||||
let expectedOrderedDictionary: OrderedDictionary<String, Int> = [
|
||||
("B", 5),
|
||||
("A", 1),
|
||||
("C", 3)
|
||||
]
|
||||
|
||||
expect(self.orderedDictionary.count) == 3
|
||||
expect(self.orderedDictionary == expectedOrderedDictionary).to(beTrue())
|
||||
expect(previousValue) == 2
|
||||
}
|
||||
|
||||
func testIndexBasedInsertionOfElementWithSameKeyAtItsCurrentIndex() {
|
||||
let previousValue = self.orderedDictionary.insertElement(("B", 5), atIndex: 1)
|
||||
|
||||
let expectedOrderedDictionary: OrderedDictionary<String, Int> = [
|
||||
("A", 1),
|
||||
("B", 5),
|
||||
("C", 3)
|
||||
]
|
||||
|
||||
expect(self.orderedDictionary.count) == 3
|
||||
expect(self.orderedDictionary == expectedOrderedDictionary).to(beTrue())
|
||||
expect(previousValue) == 2
|
||||
}
|
||||
|
||||
func testIndexBasedInsertionOfElementWithSameKeyAfterItsCurrentIndex() {
|
||||
let previousValue = self.orderedDictionary.insertElement(("B", 5), atIndex: 3)
|
||||
|
||||
let expectedOrderedDictionary: OrderedDictionary<String, Int> = [
|
||||
("A", 1),
|
||||
("C", 3),
|
||||
("B", 5)
|
||||
]
|
||||
|
||||
expect(self.orderedDictionary.count) == 3
|
||||
expect(self.orderedDictionary == expectedOrderedDictionary).to(beTrue())
|
||||
expect(previousValue) == 2
|
||||
}
|
||||
|
||||
// MARK: - Removal
|
||||
|
||||
func testRemoveAll() {
|
||||
|
||||
Reference in New Issue
Block a user