Skip to content

Commit d92a8a9

Browse files
natecook1000airspeedswift
authored andcommitted
Merge pull request #9462 from natecook1000/nc-dict-keys-compat (#9475)
[stdlib] Provide Swift 3 compatible Dict.keys/values
1 parent bc57cbc commit d92a8a9

File tree

4 files changed

+111
-24
lines changed

4 files changed

+111
-24
lines changed

stdlib/public/core/HashedCollections.swift.gyb

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,12 +2012,12 @@ public struct Dictionary<Key : Hashable, Value> :
20122012
@_inlineable
20132013
@available(swift, introduced: 4.0)
20142014
public func filter(
2015-
_ isIncluded: (Key, Value) throws -> Bool
2015+
_ isIncluded: (Element) throws -> Bool
20162016
) rethrows -> [Key: Value] {
20172017
var result = Dictionary()
2018-
for (key, value) in self {
2019-
if try isIncluded(key, value) {
2020-
result[key] = value
2018+
for el in self {
2019+
if try isIncluded(el) {
2020+
result[el.key] = el.value
20212021
}
20222022
}
20232023
return result
@@ -2291,6 +2291,26 @@ public struct Dictionary<Key : Hashable, Value> :
22912291
// API itself.
22922292
//
22932293

2294+
//
2295+
// Collection conformance
2296+
//
2297+
2298+
/// A Boolean value that indicates whether the dictionary is empty.
2299+
///
2300+
/// Dictionaries are empty when created with an initializer or an empty
2301+
/// dictionary literal.
2302+
///
2303+
/// var frequencies: [String: Int] = [:]
2304+
/// print(frequencies.isEmpty)
2305+
/// // Prints "true"
2306+
public var isEmpty: Bool {
2307+
return count == 0
2308+
}
2309+
}
2310+
2311+
// Maintain old `keys` and `values` types in Swift 3 mode.
2312+
2313+
extension Dictionary {
22942314
/// A collection containing just the keys of the dictionary.
22952315
///
22962316
/// When iterated over, keys appear in this collection in the same order as
@@ -2307,6 +2327,50 @@ public struct Dictionary<Key : Hashable, Value> :
23072327
/// // Prints "BR"
23082328
/// // Prints "JP"
23092329
/// // Prints "GH"
2330+
@available(swift, obsoleted: 4.0)
2331+
public var keys: LazyMapCollection<[Key: Value], Key> {
2332+
return self.lazy.map { $0.key }
2333+
}
2334+
2335+
/// A collection containing just the values of the dictionary.
2336+
///
2337+
/// When iterated over, values appear in this collection in the same order as
2338+
/// they occur in the dictionary's key-value pairs.
2339+
///
2340+
/// let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
2341+
/// print(countryCodes)
2342+
/// // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
2343+
///
2344+
/// for v in countryCodes.values {
2345+
/// print(v)
2346+
/// }
2347+
/// // Prints "Brazil"
2348+
/// // Prints "Japan"
2349+
/// // Prints "Ghana"
2350+
@available(swift, obsoleted: 4.0)
2351+
public var values: LazyMapCollection<[Key: Value], Value> {
2352+
return self.lazy.map { $0.value }
2353+
}
2354+
}
2355+
2356+
extension Dictionary {
2357+
/// A collection containing just the keys of the dictionary.
2358+
///
2359+
/// When iterated over, keys appear in this collection in the same order as
2360+
/// they occur in the dictionary's key-value pairs. Each key in the keys
2361+
/// collection has a unique value.
2362+
///
2363+
/// let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
2364+
/// print(countryCodes)
2365+
/// // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
2366+
///
2367+
/// for k in countryCodes.keys {
2368+
/// print(k)
2369+
/// }
2370+
/// // Prints "BR"
2371+
/// // Prints "JP"
2372+
/// // Prints "GH"
2373+
@available(swift, introduced: 4.0)
23102374
public var keys: Keys {
23112375
return Keys(self)
23122376
}
@@ -2326,6 +2390,7 @@ public struct Dictionary<Key : Hashable, Value> :
23262390
/// // Prints "Brazil"
23272391
/// // Prints "Japan"
23282392
/// // Prints "Ghana"
2393+
@available(swift, introduced: 4.0)
23292394
public var values: Values {
23302395
get {
23312396
return Values(self)
@@ -2335,22 +2400,6 @@ public struct Dictionary<Key : Hashable, Value> :
23352400
}
23362401
}
23372402

2338-
//
2339-
// Collection conformance
2340-
//
2341-
2342-
/// A Boolean value that indicates whether the dictionary is empty.
2343-
///
2344-
/// Dictionaries are empty when created with an initializer or an empty
2345-
/// dictionary literal.
2346-
///
2347-
/// var frequencies: [String: Int] = [:]
2348-
/// print(frequencies.isEmpty)
2349-
/// // Prints "true"
2350-
public var isEmpty: Bool {
2351-
return count == 0
2352-
}
2353-
23542403
/// A view of a dictionary's keys.
23552404
public struct Keys : Collection, Equatable {
23562405
public typealias Element = Key

validation-test/stdlib/Dictionary.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1180,10 +1180,12 @@ DictionaryTestSuite.test("COW.Fast.ValuesAccessDoesNotReallocate") {
11801180
assert(d1.values[i] == 1010)
11811181
assert(d1[i] == (10, 1010))
11821182

1183+
#if swift(>=4.0)
11831184
d2.values[i] += 1
11841185
assert(d2.values[i] == 1011)
11851186
assert(d2[10]! == 1011)
11861187
assert(identity1 != d2._rawIdentifier())
1188+
#endif
11871189

11881190
assert(d1[10]! == 1010)
11891191
assert(identity1 == d1._rawIdentifier())
@@ -1242,8 +1244,10 @@ DictionaryTestSuite.test("COW.Fast.KeysAccessDoesNotReallocate") {
12421244
// keys.index(of:) - O(1) bucket + linear search
12431245
MinimalHashableValue.timesEqualEqualWasCalled = 0
12441246
let l = d2.keys.index(of: lastKey)!
1247+
#if swift(>=4.0)
12451248
expectLE(MinimalHashableValue.timesEqualEqualWasCalled, 4)
1246-
1249+
#endif
1250+
12471251
expectEqual(j, k)
12481252
expectEqual(k, l)
12491253
}

validation-test/stdlib/HashedCollectionFilter3.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-run-stdlib-swift
1+
// RUN: %target-run-stdlib-swift -swift-version 3
22
// REQUIRES: executable_test
33

44
import StdlibUnittest
@@ -17,5 +17,21 @@ FilterTestSuite.test("Set.filter(_:) -> [Element]") {
1717
expectTrue(f is [Int])
1818
}
1919

20+
FilterTestSuite.test("Dictionary.keys -> LazyMapCollection") {
21+
let d = [10: 1010, 20: 1020, 30: 1030, 40: 1040]
22+
// .keys should produce a LazyMapCollection in Swift 3
23+
let f: Any = d.keys
24+
let g = f as! LazyMapCollection<[Int: Int], Int>
25+
expectEqual(4, g.count)
26+
}
27+
28+
FilterTestSuite.test("Dictionary.values -> LazyMapCollection") {
29+
let d = [10: 1010, 20: 1020, 30: 1030, 40: 1040]
30+
// .values should produce a LazyMapCollection in Swift 3
31+
let f: Any = d.values
32+
let g = f as! LazyMapCollection<[Int: Int], Int>
33+
expectEqual(4, g.count)
34+
}
35+
2036
runAllTests()
2137

validation-test/stdlib/HashedCollectionFilter4.swift

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ FilterTestSuite.test("Dictionary.filter(_:) -> [Key: Value]")
1010
{
1111
let d = [10: 1010, 20: 1020, 30: 1030, 40: 1040]
1212
// filter(_:) should produce a dictionary in Swift 4
13-
let f: Any = d.filter { (k, v) in k > 20 }
13+
let f: Any = d.filter { $0.key > 20 }
1414
expectTrue(f is [Int: Int])
1515
}
1616

1717
FilterTestSuite.test("Dictionary.filter(_:) -> [(Key, Value)] available") {
1818
let d = [10: 1010, 20: 1020, 30: 1030, 40: 1040]
1919
// The Array-returning version from Sequence should still be accessible
20-
let f: [(Int, Int)] = d.filter { (k, v) in k > 20 }
20+
let f: [(Int, Int)] = d.filter { $0.key > 20 }
2121
expectEqual(2, f.count)
2222
}
2323

@@ -37,5 +37,23 @@ FilterTestSuite.test("Set.filter(_:) -> [Element] available") {
3737
expectEqual(2, f.count)
3838
}
3939

40+
FilterTestSuite.test("Dictionary.keys -> Keys")
41+
.xfail(.always("Not actually running under Swift 4")).code
42+
{
43+
let d = [10: 1010, 20: 1020, 30: 1030, 40: 1040]
44+
// .keys should produce a Dictionary.Keys in Swift 4
45+
let f: Any = d.keys
46+
expectTrue(f is Dictionary<Int, Int>.Keys)
47+
}
48+
49+
FilterTestSuite.test("Dictionary.values -> Values")
50+
.xfail(.always("Not actually running under Swift 4")).code
51+
{
52+
let d = [10: 1010, 20: 1020, 30: 1030, 40: 1040]
53+
// .values should produce a Dictionary.Values in Swift 4
54+
let f: Any = d.values
55+
expectTrue(f is Dictionary<Int, Int>.Values)
56+
}
57+
4058
runAllTests()
4159

0 commit comments

Comments
 (0)