Compare commits

...

30 Commits

Author SHA1 Message Date
Lukas Kubanek 56bfdfc953 Bumped version to 2.2.0
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-04-04 12:26:30 +02:00
Lukas Kubanek 34efc031a4 Moved safe extension API flag back to target level
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-04-04 12:20:01 +02:00
Lukas Kubanek 3541842cd3 Enabled safe extension API flag on project level
This refines #50 and applies the change to the macOS target as well.

Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-04-04 12:18:26 +02:00
Lukas Kubanek d75fe1429b Merge pull request #50 from graphiclife/master
Issue #10: Safe for app extensions
2019-04-04 12:14:34 +02:00
Måns Siljehav f8d5a75dd5 Issue #10: Safe for app extensions
• Checked the "Require Only App-Extension-Safe API" box in the Build Settings for the OrderedDictionary-iOS target.
2019-04-04 11:15:44 +02:00
Lukas Kubanek 596a7d2c1b Changed handling of modifiers in extensions
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-03-25 08:26:41 +01:00
Lukas Kubanek f2a320bc6b Initial migration to Xcode 10.2
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-03-24 15:17:52 +01:00
Lukas Kubanek f36353d61f 2018 → 2019
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-01-11 20:21:01 +01:00
Lukas Kubanek fb30ee0cc3 Fixed a reference link
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-01-08 18:14:34 +01:00
Lukas Kubanek 4234d43565 Merge pull request #48 from gl2748/patch-1
Update package.swift
2018-10-02 22:59:51 +02:00
Iain Maitland 77d0b4937a Update package.swift
Per:
`swiftLanguageVersions` needs to be an `Int`
*Per*
https://github.com/apple/swift-package-manager/blob/master/Documentation/PackageDescriptionV4.md#package
and
https://github.com/apple/swift-package-manager/blob/master/Documentation/PackageDescriptionV4.md#swiftlanguageversions

This is causing a failing CI test for me.
2018-10-01 14:50:54 -04:00
Lukas Kubanek 4c89d79979 Bumped version to 2.1.0 2018-07-10 15:15:50 +02:00
Lukas Kubanek 397e3e4c20 Minor tweaks to the README 2018-07-10 15:11:26 +02:00
Lukas Kubanek a4abc2ee8b Updated README
- Add installation note for SPM
- Add note about no support for CocoaPods
2018-07-10 15:09:53 +02:00
Lukas Kubanek 2e54a9935b Improved #if macro 2018-07-10 14:26:35 +02:00
Lukas Kubanek ea47632047 One more refactoring of tests 2018-07-10 14:23:43 +02:00
Lukas Kubanek 1d9696939a Added initial support for SPM
Closes #42
2018-07-10 13:19:31 +02:00
Lukas Kubanek 1a26252cf7 Annotated sort methods with throws keyword 2018-07-10 13:01:31 +02:00
Lukas Kubanek 0d73c529f2 Added methods for popping/removing first and last key-value pairs
Thanks to @maicki for initial ideas

Closes #33
2018-07-10 12:53:07 +02:00
Lukas Kubanek 42030fb42a Reordered sections in OrderedDictionary 2018-07-10 12:33:29 +02:00
Lukas Kubanek e689725b4d Bumped year in license file 2018-07-10 11:57:37 +02:00
Lukas Kubanek b896bb0751 Removed empty header file 2018-07-10 11:55:38 +02:00
Lukas Kubanek 37bfcd67b2 Wrapped long method declarations 2018-07-10 11:53:52 +02:00
Lukas Kubanek cb7638e658 Added test for creation from a Dictionary
Closes #39
2018-07-10 11:53:52 +02:00
Lukas Kubanek 95e5cc9c11 Refactored tests 2018-07-10 11:53:37 +02:00
Lukas Kubanek 917cb33775 Introduced Dictionary.sorted(by:)
Refs #39
2018-07-10 11:53:37 +02:00
Lukas Kubanek 0b061bb25d Merge pull request #47 from maicki/maicki/improve-lookup
Improve key lookup
2018-07-10 11:26:54 +02:00
Michael Schneider 1d439a86ed Improve key lookup 2018-07-09 09:44:56 -07:00
Lukas Kubanek be3d9f1c69 Updated to Swift 4.2 & Xcode 10 2018-06-06 10:00:23 +02:00
Lukas Kubanek f89f30b9d1 Update README.md 2018-05-22 16:03:28 +02:00
13 changed files with 413 additions and 185 deletions
+3
View File
@@ -27,3 +27,6 @@ DerivedData
# Carthage
Carthage
# SPM
.build
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015-2017 Lukas Kubanek
Copyright (c) 2015-2019 Lukas Kubanek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+21 -20
View File
@@ -8,12 +8,10 @@
/* Begin PBXBuildFile section */
8055B0421E201C5D009DC3EE /* OrderedDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8055B0381E201C5D009DC3EE /* OrderedDictionary.framework */; };
8055B0551E201D24009DC3EE /* OrderedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 8055B0531E201D24009DC3EE /* OrderedDictionary.h */; settings = {ATTRIBUTES = (Public, ); }; };
8055B0591E201DF3009DC3EE /* OrderedDictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8055B0581E201DF3009DC3EE /* OrderedDictionaryTests.swift */; };
80A203A11F3F483700622481 /* OrderedDictionary+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80A203A01F3F483700622481 /* OrderedDictionary+Codable.swift */; };
80A203A21F3F4C1F00622481 /* OrderedDictionary+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80A203A01F3F483700622481 /* OrderedDictionary+Codable.swift */; };
80B28EA01E201EC9007E3A77 /* OrderedDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80B28E971E201EC8007E3A77 /* OrderedDictionary.framework */; };
80B28EAE1E201F15007E3A77 /* OrderedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 8055B0531E201D24009DC3EE /* OrderedDictionary.h */; settings = {ATTRIBUTES = (Public, ); }; };
80B28EB01E201F1C007E3A77 /* OrderedDictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8055B0581E201DF3009DC3EE /* OrderedDictionaryTests.swift */; };
80E8E21D1E20301E00395E49 /* OrderedDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E8E21C1E20301E00395E49 /* OrderedDictionary.swift */; };
80E8E21F1E20425B00395E49 /* OrderedDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E8E21C1E20301E00395E49 /* OrderedDictionary.swift */; };
@@ -43,7 +41,6 @@
804879381E217CA100AD31A3 /* validate-playgrounds.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "validate-playgrounds.sh"; sourceTree = "<group>"; };
8055B0381E201C5D009DC3EE /* OrderedDictionary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OrderedDictionary.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8055B0411E201C5D009DC3EE /* OrderedDictionary_Mac_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OrderedDictionary_Mac_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
8055B0531E201D24009DC3EE /* OrderedDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OrderedDictionary.h; sourceTree = "<group>"; };
8055B0581E201DF3009DC3EE /* OrderedDictionaryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrderedDictionaryTests.swift; sourceTree = "<group>"; };
807AA68F1F1E587A00576474 /* OrderedDictionary+Codable.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "OrderedDictionary+Codable.playground"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
80A203A01F3F483700622481 /* OrderedDictionary+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OrderedDictionary+Codable.swift"; sourceTree = "<group>"; };
@@ -52,6 +49,9 @@
80B28EB41E201F81007E3A77 /* Info-Tests.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Tests.plist"; sourceTree = "<group>"; };
80B28EB51E201F81007E3A77 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
80B28EB71E2020DD007E3A77 /* OrderedDictionary.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = OrderedDictionary.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
80DE329220F4CAFA0053EDA7 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
80DE329320F4DD910053EDA7 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
80DE329420F4DD910053EDA7 /* LICENSE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = "<group>"; };
80E8E21C1E20301E00395E49 /* OrderedDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrderedDictionary.swift; sourceTree = "<group>"; };
80E8E22F1E2133D100395E49 /* OrderedDictionary+Description.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OrderedDictionary+Description.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -102,6 +102,9 @@
8055B02E1E201C5D009DC3EE = {
isa = PBXGroup;
children = (
80DE329320F4DD910053EDA7 /* README.md */,
80DE329420F4DD910053EDA7 /* LICENSE.md */,
80DE329220F4CAFA0053EDA7 /* Package.swift */,
8055B0521E201D24009DC3EE /* Sources */,
80B28EB11E201F72007E3A77 /* Playgrounds */,
8055B0571E201DF3009DC3EE /* Tests */,
@@ -125,7 +128,6 @@
8055B0521E201D24009DC3EE /* Sources */ = {
isa = PBXGroup;
children = (
8055B0531E201D24009DC3EE /* OrderedDictionary.h */,
80E8E21C1E20301E00395E49 /* OrderedDictionary.swift */,
80A203A01F3F483700622481 /* OrderedDictionary+Codable.swift */,
80E8E22F1E2133D100395E49 /* OrderedDictionary+Description.swift */,
@@ -166,7 +168,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
8055B0551E201D24009DC3EE /* OrderedDictionary.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -174,7 +175,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
80B28EAE1E201F15007E3A77 /* OrderedDictionary.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -260,37 +260,38 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0820;
LastUpgradeCheck = 0930;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "Lukas Kubanek";
TargetAttributes = {
8055B0371E201C5D009DC3EE = {
CreatedOnToolsVersion = 8.2.1;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
8055B0401E201C5D009DC3EE = {
CreatedOnToolsVersion = 8.2.1;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
80B28E961E201EC8007E3A77 = {
CreatedOnToolsVersion = 8.2.1;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
80B28E9E1E201EC9007E3A77 = {
CreatedOnToolsVersion = 8.2.1;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 8055B0321E201C5D009DC3EE /* Build configuration list for PBXProject "OrderedDictionary" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 8055B02E1E201C5D009DC3EE;
productRefGroup = 8055B0391E201C5D009DC3EE /* Products */;
@@ -393,6 +394,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@@ -446,6 +448,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
@@ -455,6 +458,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
@@ -500,6 +504,7 @@
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
@@ -508,6 +513,7 @@
8055B04D1E201C5D009DC3EE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_CODE_COVERAGE = NO;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
@@ -522,13 +528,13 @@
PRODUCT_BUNDLE_IDENTIFIER = com.lukaskubanek.OrderedDictionary;
PRODUCT_NAME = OrderedDictionary;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
8055B04E1E201C5D009DC3EE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_CODE_COVERAGE = NO;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
@@ -543,7 +549,6 @@
PRODUCT_BUNDLE_IDENTIFIER = com.lukaskubanek.OrderedDictionary;
PRODUCT_NAME = OrderedDictionary;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -556,7 +561,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.lukaskubanek.OrderedDictionaryTests;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -569,13 +573,13 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.lukaskubanek.OrderedDictionaryTests;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SWIFT_VERSION = 4.0;
};
name = Release;
};
80B28EA91E201EC9007E3A77 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_CODE_COVERAGE = NO;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
@@ -590,7 +594,6 @@
PRODUCT_NAME = OrderedDictionary;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -598,6 +601,7 @@
80B28EAA1E201EC9007E3A77 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_CODE_COVERAGE = NO;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
@@ -612,7 +616,6 @@
PRODUCT_NAME = OrderedDictionary;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@@ -627,7 +630,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.lukaskubanek.OrderedDictionary-iOSTests";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -640,7 +642,6 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.lukaskubanek.OrderedDictionary-iOSTests";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
SWIFT_VERSION = 4.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0930"
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0930"
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
+27
View File
@@ -0,0 +1,27 @@
// swift-tools-version:4.2
import PackageDescription
let package = Package(
name: "OrderedDictionary",
products: [
.library(
name: "OrderedDictionary",
targets: ["OrderedDictionary"]
)
],
dependencies: [],
targets: [
.target(
name: "OrderedDictionary",
dependencies: [],
path: "Sources"
),
.testTarget(
name: "OrderedDictionaryTests",
dependencies: ["OrderedDictionary"],
path: "Tests"
)
],
swiftLanguageVersions: [4]
)
+25 -12
View File
@@ -1,6 +1,7 @@
# OrderedDictionary
[![](https://img.shields.io/travis/lukaskubanek/OrderedDictionary.svg?style=flat-square "Build")](https://travis-ci.org/lukaskubanek/OrderedDictionary) [![](https://img.shields.io/badge/release-v1.1.0-blue.svg?style=flat-square)](https://github.com/lukaskubanek/OrderedDictionary/releases) [![](https://img.shields.io/badge/Swift-4.0+-orange.svg?style=flat-square)](https://developer.apple.com/swift/ "Swift 4") ![](https://img.shields.io/badge/platform-macOS,%20iOS-yellowgreen.svg?style=flat-square "Platform: macOS,%20iOS") [![](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat-square "Carthage compatible")](https://github.com/Carthage/Carthage) [![](https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat-square "License: MIT")](LICENSE.md)
[![](https://img.shields.io/travis/lukaskubanek/OrderedDictionary.svg?style=flat-square "Build")](https://travis-ci.org/lukaskubanek/OrderedDictionary) [![](https://img.shields.io/badge/release-v2.2.0-blue.svg?style=flat-square)](https://github.com/lukaskubanek/OrderedDictionary/releases) [![](https://img.shields.io/badge/Swift-4.0+-orange.svg?style=flat-square)](https://developer.apple.com/swift/ "Swift 4") ![](https://img.shields.io/badge/platform-macOS/iOS-yellowgreen.svg?style=flat-square "Platform: macOS/iOS") [![](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat-square "Carthage compatible")](https://github.com/Carthage/Carthage)
[![](https://img.shields.io/badge/SPM-compatible-brightgreen.svg?style=flat-square "SPM compatible")](https://github.com/Carthage/Carthage) [![](https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat-square "License: MIT")](LICENSE.md)
**OrderedDictionary** is a lightweight implementation of an ordered dictionary data structure in Swift.
@@ -12,27 +13,39 @@ Internally, `OrderedDictionary` uses a backing store composed of an instance of
## Requirements
- Swift 4.0+
- Swift 4.0, 4.2, 5.0
- Xcode 9.2+
- iOS 8.0+ / macOS 10.10+
## Installation
This library is distributed as a Swift framework and can be integrated into your project in following ways:
The library is distributed as a Swift framework and can be integrated into your project in following ways:
### Carthage
#### Carthage
The easiest way is to use the package manager [Carthage](https://github.com/Carthage/Carthage).
If you use [Carthage](https://github.com/Carthage/Carthage) for managing your dependencies, put OrderedDictionary into your `Cartfile`:
1. Add `github "lukaskubanek/OrderedDictionary"` to your `Cartfile`.
2. Run `carthage bootstrap`.
3. Drag either the `OrderedDictionary.xcodeproj` or the `OrderedDictionary.framework` into your project/workspace and link your target against the `OrderedDictionary.framework`.
4. Make sure the framework [gets copied](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to your application bundle.
5. Import the framework using `import OrderedDictionary`.
```plain
github "lukaskubanek/OrderedDictionary"
```
### Submodule & Xcode Project
Then, drag either the `OrderedDictionary.xcodeproj` or the `OrderedDictionary.framework` into your project/workspace and link your target against the `OrderedDictionary.framework`. Also make sure that the framework [gets copied](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to your application bundle.
Another option is to use [Git submodules](http://git-scm.com/book/en/v2/Git-Tools-Submodules) and integrating the Xcode project `OrderedDictionary.xcodeproj` directly to your Xcode workspace.
#### Swift Package Manager
Another option is to use the [Swift Package Manager](https://swift.org/package-manager/). If you prefer this option, put OrderedDictionary as a dependency to your `Package.swift`:
```plain
.package(url: "https://github.com/lukaskubanek/OrderedDictionary.git", from: "2.2.0")
```
#### Git Submodules
Yet another option is using [Git submodules](http://git-scm.com/book/en/v2/Git-Tools-Submodules) and integrating the Xcode project `OrderedDictionary.xcodeproj` from the submodule directly to your Xcode workspace.
#### ⚠️ Note About CocoaPods
Although there is high demand for [CocoaPods](https://cocoapods.org) support, this method won't be officially supported by this library. Since I'm not using CocoaPods myself and since I think this method will be once replaced by the Swift Package Manager, I don't want to put any effort in maintaining an official podspec. If you really want to include this library via CocoaPods, there is still a way by creating a custom podspec (see the last section of [this post](https://guides.cocoapods.org/syntax/podfile.html#pod)).
## Usage & Docs
+4 -2
View File
@@ -120,9 +120,11 @@ extension OrderedDictionary: Decodable {
#endif
fileprivate extension DecodingError {
extension DecodingError {
fileprivate static func unkeyedContainerReachedEndBeforeValue(_ codingPath: [CodingKey]) -> DecodingError {
fileprivate static func unkeyedContainerReachedEndBeforeValue(
_ codingPath: [CodingKey]
) -> DecodingError {
return DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: codingPath,
+1 -1
View File
@@ -20,7 +20,7 @@ extension OrderedDictionary {
fileprivate func makeDescription(debug: Bool) -> String {
// The implementation of the description is inspired by zwaldowski's implementation of the
// ordered dictionary. See http://bit.ly/2iqGhrb
// ordered dictionary. See https://bit.ly/2RiWfJu
if isEmpty { return "[:]" }
View File
+123 -56
View File
@@ -36,7 +36,10 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
/// - Parameter values: The sequence of values.
/// - Parameter getKey: The closure which provides a key for the given value from the values
/// sequence.
public init<Values: Sequence>(values: Values, keyedBy getKey: (Value) -> Key) where Values.Element == Value {
public init<Values: Sequence>(
values: Values,
keyedBy getKey: (Value) -> Key
) where Values.Element == Value {
self.init(values.map { (getKey($0), $0) })
}
@@ -54,8 +57,11 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
///
/// - Parameter unsorted: The unsorted dictionary.
/// - Parameter areInIncreasingOrder: The sort function which compares the key-value pairs.
public init(unsorted: Dictionary<Key, Value>, areInIncreasingOrder: (Element, Element) -> Bool) {
let elements = unsorted
public init(
unsorted: Dictionary<Key, Value>,
areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows {
let elements = try unsorted
.map { (key: $0.key, value: $0.value) }
.sorted(by: areInIncreasingOrder)
@@ -96,6 +102,49 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
return _keysToValues
}
// ======================================================= //
// MARK: - Indices
// ======================================================= //
/// The indices that are valid for subscripting the ordered dictionary.
public var indices: Indices {
return _orderedKeys.indices
}
/// The position of the first key-value pair in a non-empty ordered dictionary.
public var startIndex: Index {
return _orderedKeys.startIndex
}
/// The position which is one greater than the position of the last valid key-value pair in the
/// ordered dictionary.
public var endIndex: Index {
return _orderedKeys.endIndex
}
/// Returns the position immediately after the given index.
public func index(after i: Index) -> Index {
return _orderedKeys.index(after: i)
}
/// Returns the position immediately before the given index.
public func index(before i: Index) -> Index {
return _orderedKeys.index(before: i)
}
// ======================================================= //
// MARK: - Slices
// ======================================================= //
/// Accesses a contiguous subrange of the ordered dictionary.
///
/// - Parameter bounds: A range of the ordered dictionary's indices. The bounds of the range
/// must be valid indices of the ordered dictionary.
/// - Returns: The slice view at the ordered dictionary in the specified subrange.
public subscript(bounds: Range<Index>) -> SubSequence {
return OrderedDictionarySlice(base: self, bounds: bounds)
}
// ======================================================= //
// MARK: - Key-based Access
// ======================================================= //
@@ -134,7 +183,7 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
/// - Parameter key: The key to be looked up.
/// - Returns: `true` if the ordered dictionary contains the given key; otherwise, `false`.
public func containsKey(_ key: Key) -> Bool {
return _orderedKeys.contains(key)
return _keysToValues[key] != nil
}
/// Returns the value associated with the given key if the key is found in the ordered
@@ -151,13 +200,13 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
/// key-value pair if the key does not exist.
///
/// - Parameter value: The new value to add to the ordered dictionary.
/// - Parameter key: The key to associate with `value`. If `key` already exists in the ordered
/// - Parameter key: The key to associate with `value`. If `key` already exists in the ordered
/// dictionary, `value` replaces the existing associated value. If `key` is not already a key
/// of the ordered dictionary, the `(key, value)` pair is appended at the end of the ordered
/// dictionary.
@discardableResult
public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? {
if _orderedKeys.contains(key) {
if containsKey(key) {
let currentValue = _unsafeValue(forKey: key)
_keysToValues[key] = value
@@ -385,7 +434,11 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
return element
}
private func _canUpdate(_ newElement: Element, at index: Index, keyPresentAtIndex: inout Bool) -> Bool {
private func _canUpdate(
_ newElement: Element,
at index: Index,
keyPresentAtIndex: inout Bool
) -> Bool {
precondition(indices.contains(index), "OrderedDictionary index is out of range")
let currentIndexOfKey = self.index(forKey: newElement.key)
@@ -396,6 +449,34 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
return keyNotPresent || keyPresentAtIndex
}
// ======================================================= //
// MARK: - Removing First & Last Elements
// ======================================================= //
/// Removes and returns the first key-value pair of the ordered dictionary if it is not empty.
public mutating func popFirst() -> Element? {
guard !isEmpty else { return nil }
return remove(at: startIndex)
}
/// Removes and returns the last key-value pair of the ordered dictionary if it is not empty.
public mutating func popLast() -> Element? {
guard !isEmpty else { return nil }
return remove(at: index(before: endIndex))
}
/// Removes and returns the first key-value pair of the ordered dictionary.
public mutating func removeFirst() -> Element {
precondition(!isEmpty, "Cannot remove key-value pairs from empty OrderedDictionary")
return remove(at: startIndex)!
}
/// Removes and returns the last key-value pair of the ordered dictionary.
public mutating func removeLast() -> Element {
precondition(!isEmpty, "Cannot remove key-value pairs from empty OrderedDictionary")
return remove(at: index(before: endIndex))!
}
// ======================================================= //
// MARK: - Moving Elements
// ======================================================= //
@@ -442,8 +523,10 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
/// should be ordered before its second argument; otherwise, `false`.
///
/// - SeeAlso: MutableCollection.sort(by:), sorted(by:)
public mutating func sort(by areInIncreasingOrder: (Element, Element) -> Bool) {
_orderedKeys = _sortedElements(by: areInIncreasingOrder).map { $0.key }
public mutating func sort(
by areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows {
_orderedKeys = try _sortedElements(by: areInIncreasingOrder).map { $0.key }
}
/// Returns a new ordered dictionary, sorted using the given predicate as the comparison between
@@ -457,55 +540,16 @@ public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
///
/// - SeeAlso: MutableCollection.sorted(by:), sort(by:)
/// - MutatingVariant: sort
public func sorted(by areInIncreasingOrder: (Element, Element) -> Bool) -> OrderedDictionary<Key, Value> {
return OrderedDictionary(_sortedElements(by: areInIncreasingOrder))
public func sorted(
by areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows -> OrderedDictionary<Key, Value> {
return OrderedDictionary(try _sortedElements(by: areInIncreasingOrder))
}
private func _sortedElements(by areInIncreasingOrder: (Element, Element) -> Bool) -> [Element] {
return sorted(by: areInIncreasingOrder)
}
// ======================================================= //
// MARK: - Slices
// ======================================================= //
/// Accesses a contiguous subrange of the ordered dictionary.
///
/// - Parameter bounds: A range of the ordered dictionary's indices. The bounds of the range
/// must be valid indices of the ordered dictionary.
/// - Returns: The slice view at the ordered dictionary in the specified subrange.
public subscript(bounds: Range<Index>) -> SubSequence {
return OrderedDictionarySlice(base: self, bounds: bounds)
}
// ======================================================= //
// MARK: - Indices
// ======================================================= //
/// The indices that are valid for subscripting the ordered dictionary.
public var indices: Indices {
return _orderedKeys.indices
}
/// The position of the first key-value pair in a non-empty ordered dictionary.
public var startIndex: Index {
return _orderedKeys.startIndex
}
/// The position which is one greater than the position of the last valid key-value pair in the
/// ordered dictionary.
public var endIndex: Index {
return _orderedKeys.endIndex
}
/// Returns the position immediately after the given index.
public func index(after i: Index) -> Index {
return _orderedKeys.index(after: i)
}
/// Returns the position immediately before the given index.
public func index(before i: Index) -> Index {
return _orderedKeys.index(before: i)
private func _sortedElements(
by areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows -> [Element] {
return try sorted(by: areInIncreasingOrder)
}
// ======================================================= //
@@ -608,3 +652,26 @@ extension OrderedDictionary where Value: Equatable {
}
}
// ======================================================= //
// MARK: - Dictionary Extension
// ======================================================= //
extension Dictionary {
/// Returns an ordered dictionary containing the key-value pairs from the dictionary, sorted
/// using the given sort function.
///
/// - Parameter areInIncreasingOrder: The sort function which compares the key-value pairs.
/// - Returns: The ordered dictionary.
/// - SeeAlso: OrderedDictionary.init(unsorted:areInIncreasingOrder:)
public func sorted(
by areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows -> OrderedDictionary<Key, Value> {
return try OrderedDictionary(
unsorted: self,
areInIncreasingOrder: areInIncreasingOrder
)
}
}
+2 -2
View File
@@ -15,13 +15,13 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<string>2.2.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2015-2018 Lukas Kubanek. All rights reserved.</string>
<string>Copyright © 2015-2019 Lukas Kubanek. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
+204 -89
View File
@@ -2,8 +2,7 @@ import OrderedDictionary
import Foundation
import XCTest
#if swift(>=4.1)
#else
#if !swift(>=4.1)
/// This is a shim for testing the equality in Swift <4.1.
public func XCTAssertEqual<K, V: Equatable>(
@@ -20,7 +19,7 @@ public func XCTAssertEqual<K, V: Equatable>(
line: line
)
}
#endif
struct TestValue: Equatable {
@@ -37,65 +36,82 @@ class OrderedDictionaryTests: XCTestCase {
// ======================================================= //
func testInitializationUsingArrayLiteral() {
let actual: OrderedDictionary<String, Int> = [
("A", 1),
("B", 2),
("C", 3)
]
let expected = OrderedDictionary<String, Int>([
(key: "A", value: 1),
(key: "B", value: 2),
(key: "C", value: 3)
])
let actual: OrderedDictionary<String, Int> = [("A", 1), ("B", 2), ("C", 3)]
XCTAssertEqual(expected, actual)
XCTAssertEqual(actual, expected)
}
func testInitializationUsingDictionaryLiteral() {
let actual: OrderedDictionary<String, Int> = [
"A": 1,
"B": 2,
"C": 3
]
let expected = OrderedDictionary<String, Int>([
(key: "A", value: 1),
(key: "B", value: 2),
(key: "C", value: 3)
])
let actual: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
XCTAssertEqual(expected, actual)
XCTAssertEqual(actual, expected)
}
func testInitializationUsingValuesAndKeyProviderClosure() {
let values = [1, 2, 3]
let actual = OrderedDictionary(
values: [1, 2, 3],
keyedBy: { "\($0)" }
)
let expected = OrderedDictionary<String, Int>([
(key: "1", value: 1),
(key: "2", value: 2),
(key: "3", value: 3)
])
let actual = OrderedDictionary(values: values, keyedBy: { "\($0)" })
XCTAssertEqual(expected, actual)
XCTAssertEqual(actual, expected)
}
func testInitializationUsingValuesAnyKeyPath() {
let values = [
TestValue(string: "A"),
TestValue(string: "B"),
TestValue(string: "C")
]
let actual = OrderedDictionary(
values: [
TestValue(string: "A"),
TestValue(string: "B"),
TestValue(string: "C")
],
keyedBy: \.string
)
let expected = OrderedDictionary<String, TestValue>([
(key: "A", value: TestValue(string: "A")),
(key: "B", value: TestValue(string: "B")),
(key: "C", value: TestValue(string: "C"))
])
let actual = OrderedDictionary(values: values, keyedBy: \.string)
XCTAssertEqual(expected, actual)
XCTAssertEqual(actual, expected)
}
func testInitializationUsingUnsortedDictionaryAndSortFunction() {
let unsorted = [
2: "foo",
1: "bar",
4: "baz",
5: "bat",
3: "bam"
]
let actual = OrderedDictionary(
unsorted: [
2: "foo",
1: "bar",
4: "baz",
5: "bat",
3: "bam"
],
areInIncreasingOrder: { $0.key < $1.key }
)
let expected = OrderedDictionary([
(key: 1, value: "bar"),
@@ -104,9 +120,28 @@ class OrderedDictionaryTests: XCTestCase {
(key: 4, value: "baz"),
(key: 5, value: "bat")
])
let actual = OrderedDictionary(unsorted: unsorted, areInIncreasingOrder: { $0.key < $1.key })
XCTAssertEqual(expected, actual)
XCTAssertEqual(actual, expected)
}
func testCreationFromDictionary() {
let actual = [
2: "foo",
1: "bar",
4: "baz",
5: "bat",
3: "bam"
].sorted(by: { $0.key < $1.key })
let expected = OrderedDictionary([
(key: 1, value: "bar"),
(key: 2, value: "foo"),
(key: 3, value: "bam"),
(key: 4, value: "baz"),
(key: 5, value: "bat")
])
XCTAssertEqual(actual, expected)
}
// ======================================================= //
@@ -148,8 +183,8 @@ class OrderedDictionaryTests: XCTestCase {
let index = indexesIterator.next()
let (expectedKey, expectedValue) = orderedDictionary[index!]
XCTAssertEqual(expectedKey, actualKey)
XCTAssertEqual(expectedValue, actualValue)
XCTAssertEqual(actualKey, expectedKey)
XCTAssertEqual(actualValue, expectedValue)
}
XCTAssertNil(iterator.next())
@@ -158,29 +193,29 @@ class OrderedDictionaryTests: XCTestCase {
func testAccessingOrderedKeys() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let expected = ["A", "B", "C"]
let actual = Array(orderedDictionary.orderedKeys)
XCTAssertEqual(expected, actual)
let expected = ["A", "B", "C"]
XCTAssertEqual(actual, expected)
}
func testAccessingOrderedValues() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let expected = [1, 2, 3]
let actual = Array(orderedDictionary.orderedValues)
XCTAssertEqual(expected, actual)
let expected = [1, 2, 3]
XCTAssertEqual(actual, expected)
}
func testAccessingUnsortedDictionary() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let expected = ["A": 1, "B": 2, "C": 3]
let actual = orderedDictionary.unorderedDictionary
XCTAssertEqual(expected, actual)
let expected = ["A": 1, "B": 2, "C": 3]
XCTAssertEqual(actual, expected)
}
// ======================================================= //
@@ -223,11 +258,11 @@ class OrderedDictionaryTests: XCTestCase {
orderedDictionary.insert((key: "U", value: 16), at: 2)
orderedDictionary.insert((key: "V", value: 17), at: 5)
orderedDictionary.insert((key: "W", value: 18), at: 2)
let expected: OrderedDictionary<String, Int> = ["T": 15, "A": 1, "W": 18, "U": 16, "B": 2, "C": 3, "V": 17]
let actual = orderedDictionary
XCTAssertEqual(expected, actual)
let expected: OrderedDictionary<String, Int> = ["T": 15, "A": 1, "W": 18, "U": 16, "B": 2, "C": 3, "V": 17]
XCTAssertEqual(actual, expected)
}
func testIndexBasedInsertionWithDuplicateKey() {
@@ -262,10 +297,10 @@ class OrderedDictionaryTests: XCTestCase {
XCTAssertEqual(orderedDictionary.count, 3)
XCTAssertTrue(previousElement! == ("B", 2))
let expected: OrderedDictionary<String, Int> = ["A": 1, "D": 4, "C": 3]
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["A": 1, "D": 4, "C": 3]
XCTAssertEqual(expected, actual)
XCTAssertEqual(actual, expected)
}
func testIndexBasedUpdateMethodByReplacingSameKey() {
@@ -275,10 +310,10 @@ class OrderedDictionaryTests: XCTestCase {
XCTAssertEqual(orderedDictionary.count, 3)
XCTAssertTrue(previousElement! == ("B", 2))
let expected: OrderedDictionary<String, Int> = ["A": 1, "B": 42, "C": 3]
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["A": 1, "B": 42, "C": 3]
XCTAssertEqual(expected, actual)
XCTAssertEqual(actual, expected)
}
func testIndexBasedUpdateMethodByDuplicatingKey() {
@@ -332,26 +367,100 @@ class OrderedDictionaryTests: XCTestCase {
func testIndexBasedRemoval() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let (expectedKey1, expectedValue1) = ("A", 1)
let (actualKey1, actualValue1) = orderedDictionary.remove(at: 0)!
let (expectedKey1, expectedValue1) = ("A", 1)
XCTAssertEqual(expectedKey1, actualKey1)
XCTAssertEqual(expectedValue1, actualValue1)
XCTAssertEqual(actualKey1, expectedKey1)
XCTAssertEqual(actualValue1, expectedValue1)
let (expectedKey2, expectedValue2) = ("D", 4)
let (actualKey2, actualValue2) = orderedDictionary.remove(at: 2)!
let (expectedKey2, expectedValue2) = ("D", 4)
XCTAssertEqual(expectedKey2, actualKey2)
XCTAssertEqual(expectedValue2, actualValue2)
XCTAssertEqual(actualKey2, expectedKey2)
XCTAssertEqual(actualValue2, expectedValue2)
let nonExistentElement = orderedDictionary.remove(at: 42)
XCTAssertNil(nonExistentElement)
let expected: OrderedDictionary<String, Int> = ["B": 2, "C": 3]
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["B": 2, "C": 3]
XCTAssertEqual(expected, actual)
XCTAssertEqual(actual, expected)
}
func testPopFirstEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = []
let first = orderedDictionary.popFirst()
XCTAssertNil(first)
}
func testPopFirstNonEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let (actualKey, actualValue) = orderedDictionary.popFirst()!
let (expectedKey, expectedValue) = ("A", 1)
XCTAssertEqual(actualKey, expectedKey)
XCTAssertEqual(actualValue, expectedValue)
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["B": 2, "C": 3, "D": 4]
XCTAssertEqual(actual, expected)
}
func testPopLastEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = []
let last = orderedDictionary.popLast()
XCTAssertNil(last)
}
func testPopLastNonEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let (actualKey, actualValue) = orderedDictionary.popLast()!
let (expectedKey, expectedValue) = ("D", 4)
XCTAssertEqual(actualKey, expectedKey)
XCTAssertEqual(actualValue, expectedValue)
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
XCTAssertEqual(actual, expected)
}
func testRemoveFirstNonEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let (actualKey, actualValue) = orderedDictionary.removeFirst()
let (expectedKey, expectedValue) = ("A", 1)
XCTAssertEqual(actualKey, expectedKey)
XCTAssertEqual(actualValue, expectedValue)
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["B": 2, "C": 3, "D": 4]
XCTAssertEqual(actual, expected)
}
func testRemoveLastNonEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let (actualKey, actualValue) = orderedDictionary.removeLast()
let (expectedKey, expectedValue) = ("D", 4)
XCTAssertEqual(actualKey, expectedKey)
XCTAssertEqual(actualValue, expectedValue)
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
XCTAssertEqual(actual, expected)
}
// ======================================================= //
@@ -370,38 +479,36 @@ class OrderedDictionaryTests: XCTestCase {
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["C": 3, "A": 1, "D": 4, "B": 2]
XCTAssert(actual == expected)
XCTAssertEqual(actual, expected)
}
// ======================================================= //
// MARK: - Sorting Elements
// ======================================================= //
private let areInIncreasingOrder: (OrderedDictionary<String, Int>.Element, OrderedDictionary<String, Int>.Element) -> Bool = { element1, element2 in
if element1.value == element2.value {
return element1.key < element2.key
} else {
return element1.value < element2.value
}
}
func testSortingWithMutation() {
var orderedDictionary: OrderedDictionary<String, Int> = ["E": 4, "G": 3, "A": 3, "D": 1, "B": 4]
orderedDictionary.sort(by: areInIncreasingOrder)
orderedDictionary.sort { element1, element2 in
if element1.value != element2.value { return element1.value < element2.value }
return element1.key < element2.key
}
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["D": 1, "A": 3, "G": 3, "B": 4, "E": 4]
XCTAssertTrue(actual == expected)
XCTAssertEqual(actual, expected)
}
func testSortingWithoutMutation() {
let orderedDictionary: OrderedDictionary<String, Int> = ["E": 4, "G": 3, "A": 3, "D": 1, "B": 4]
let actual: OrderedDictionary<String, Int> = orderedDictionary.sorted(by: areInIncreasingOrder)
let actual: OrderedDictionary<String, Int> = orderedDictionary.sorted { element1, element2 in
if element1.value != element2.value { return element1.value < element2.value }
return element1.key < element2.key
}
let expected: OrderedDictionary<String, Int> = ["D": 1, "A": 3, "G": 3, "B": 4, "E": 4]
XCTAssertTrue(actual.elementsEqual(expected, by: ==))
XCTAssertEqual(actual, expected)
}
// ======================================================= //
@@ -433,18 +540,18 @@ class OrderedDictionaryTests: XCTestCase {
let jsonEncoder = JSONEncoder()
let data = try! jsonEncoder.encode(orderedDictionary)
let expectedString = "[\"A\",42,\"B\",100,\"C\",11]"
let actualString = String(data: data, encoding: .utf8)
XCTAssertEqual(expectedString, actualString)
let expectedString = "[\"A\",42,\"B\",100,\"C\",11]"
XCTAssertEqual(actualString, expectedString)
let jsonDecoder = JSONDecoder()
let expected = orderedDictionary
let actual = try! jsonDecoder.decode(OrderedDictionary<String, Int>.self, from: data)
XCTAssertEqual(expected, actual)
let expected = orderedDictionary
XCTAssertEqual(actual, expected)
}
func testEncodingAndDecodingViaPropertyList() {
@@ -455,14 +562,14 @@ class OrderedDictionaryTests: XCTestCase {
]
let plistEncoder = PropertyListEncoder()
let plistDecoder = PropertyListDecoder()
let data = try! plistEncoder.encode(orderedDictionary)
let expected = orderedDictionary
let plistDecoder = PropertyListDecoder()
let actual = try! plistDecoder.decode(OrderedDictionary<String, Int>.self, from: data)
XCTAssertEqual(expected, actual)
let expected = orderedDictionary
XCTAssertEqual(actual, expected)
}
// ======================================================= //
@@ -477,39 +584,47 @@ class OrderedDictionaryTests: XCTestCase {
}
func testEmptyDescription() {
let expected = "[:]"
let orderedDictionary = OrderedDictionary<String, DescribedValue>()
let actual = orderedDictionary.description
XCTAssertEqual(expected, actual)
let expected = "[:]"
XCTAssertEqual(actual, expected)
}
func testDescription() {
let expected = "[A: 1, B: 2, C: 3]"
let orderedDictionary: OrderedDictionary<String, DescribedValue> = ["A": DescribedValue(1), "B": DescribedValue(2), "C": DescribedValue(3)]
let orderedDictionary: OrderedDictionary<String, DescribedValue> = [
"A": DescribedValue(1),
"B": DescribedValue(2),
"C": DescribedValue(3)
]
let actual = orderedDictionary.description
XCTAssertEqual(expected, actual)
let expected = "[A: 1, B: 2, C: 3]"
XCTAssertEqual(actual, expected)
}
func testEmptyDebugDescription() {
let expected = "[:]"
let orderedDictionary = OrderedDictionary<String, DescribedValue>()
let actual = orderedDictionary.debugDescription
XCTAssertEqual(expected, actual)
let expected = "[:]"
XCTAssertEqual(actual, expected)
}
func testDebugDescription() {
let expected = "[\"A\": debug(1), \"B\": debug(2), \"C\": debug(3)]"
let orderedDictionary: OrderedDictionary<String, DescribedValue> = ["A": DescribedValue(1), "B": DescribedValue(2), "C": DescribedValue(3)]
let orderedDictionary: OrderedDictionary<String, DescribedValue> = [
"A": DescribedValue(1),
"B": DescribedValue(2),
"C": DescribedValue(3)
]
let actual = orderedDictionary.debugDescription
XCTAssertEqual(expected, actual)
let expected = "[\"A\": debug(1), \"B\": debug(2), \"C\": debug(3)]"
XCTAssertEqual(actual, expected)
}
}