Compare commits

...

7 Commits

Author SHA1 Message Date
Lukas Kubanek 9074b8abe8 Updated readme 2015-09-11 10:24:58 +02:00
Lukas Kubanek 7f58e9ae8d Minor refactoring 2015-09-11 10:23:01 +02:00
Lukas Kubanek feffcd9041 Improved fatal error message for insertion using negative index 2015-09-11 10:22:53 +02:00
Lukas Kubanek e963b30ff8 Added support for index-based insertion 2015-09-11 10:17:28 +02:00
Lukas Kubanek 23725866ab Improved fatal error messages 2015-09-11 09:35:42 +02:00
Lukas Kubanek 9aa12bb2aa Updated readme 2015-09-10 21:58:39 +02:00
Lukas Kubanek 4bcf559767 Updated the Swift/Xcode requirement 2015-09-10 19:16:48 +02:00
3 changed files with 122 additions and 19 deletions
+3 -3
View File
@@ -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"
+58 -16
View File
@@ -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++
+61
View File
@@ -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() {