Skip to content

Commit 4426912

Browse files
committed
Implement mapValues and compactMapValues for CxxDictionary
1 parent 98b1494 commit 4426912

File tree

3 files changed

+135
-0
lines changed

3 files changed

+135
-0
lines changed

stdlib/public/Cxx/CxxDictionary.swift

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,60 @@ extension CxxDictionary {
144144
}
145145
}
146146

147+
@inlinable
148+
public func mapValues<R, E>(
149+
_ transform: (Value) throws(E) -> R.Value
150+
) throws(E) -> R where R: CxxDictionary, R.Key == Key {
151+
var result = R.init()
152+
153+
var iterator = __beginUnsafe()
154+
let endIterator = __endUnsafe()
155+
156+
while iterator != endIterator {
157+
let pair = iterator.pointee
158+
try result.__insertUnsafe(R.Element(first: pair.first, second: transform(pair.second)))
159+
iterator = iterator.successor()
160+
}
161+
162+
return result
163+
}
164+
165+
@inlinable
166+
@_disfavoredOverload
167+
public func mapValues<E>(
168+
_ transform: (Value) throws(E) -> Value
169+
) throws(E) -> Self {
170+
return try mapValues(transform) as Self
171+
}
172+
173+
@inlinable
174+
public func compactMapValues<R, E>(
175+
_ transform: (Value) throws(E) -> R.Value?
176+
) throws(E) -> R where R: CxxDictionary, R.Key == Key {
177+
var result = R.init()
178+
179+
var iterator = __beginUnsafe()
180+
let endIterator = __endUnsafe()
181+
182+
while iterator != endIterator {
183+
let pair = iterator.pointee
184+
if let value = try transform(pair.second) {
185+
result.__insertUnsafe(R.Element(first: pair.first, second: value))
186+
}
187+
iterator = iterator.successor()
188+
}
189+
190+
return result
191+
}
192+
193+
@inlinable
194+
@_disfavoredOverload
195+
public func compactMapValues<E>(
196+
_ transform: (Value) throws(E) -> Value?
197+
) throws(E) -> Self {
198+
return try compactMapValues(transform) as Self
199+
}
200+
147201
public func filter(_ isIncluded: (_ key: Key, _ value: Value) throws -> Bool) rethrows -> Self {
148202
var filteredDictionary = Self.init()
149203
var iterator = __beginUnsafe()

test/Interop/Cxx/stdlib/Inputs/std-map.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ using Map = std::map<int, int>;
1010
using MapStrings = std::map<std::string, std::string>;
1111
using NestedMap = std::map<int, Map>;
1212
using MapGroup = std::map<int, std::vector<int>>;
13+
using MapIntString = std::map<int, std::string>;
1314
using UnorderedMap = std::unordered_map<int, int>;
1415
using UnorderedMapGroup = std::unordered_map<int, std::vector<int>>;
16+
using UnorderedIntString = std::unordered_map<int, std::string>;
1517
inline Map initMap() { return {{1, 3}, {2, 2}, {3, 3}}; }
1618
inline UnorderedMap initUnorderedMap() { return {{1, 3}, {3, 3}, {2, 2}}; }
1719
inline Map initEmptyMap() { return {}; }

test/Interop/Cxx/stdlib/use-std-map.swift

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,85 @@ StdMapTestSuite.test("UnorderedMap.subscript(:default:)") {
267267
expectEqual(m[-5, default: 555], 555)
268268
}
269269

270+
StdMapTestSuite.test("Map.mapValues") {
271+
let m = initMap()
272+
let n = m.mapValues { v in v * 2 }
273+
expectEqual(n[1], 6)
274+
expectEqual(n[2], 4)
275+
expectEqual(n[3], 6)
276+
277+
let n2: MapIntString = m.mapValues { v in std.string("\(v * 3)") }
278+
expectEqual(n2[1], std.string("9"))
279+
expectEqual(n2[2], std.string("6"))
280+
expectEqual(n2[3], std.string("9"))
281+
282+
let n3: UnorderedMap = m.mapValues { v in v * 4 }
283+
expectEqual(n3[1], 12)
284+
expectEqual(n3[2], 8)
285+
expectEqual(n3[3], 12)
286+
}
287+
288+
StdMapTestSuite.test("UnorderedMap.mapValues") {
289+
let m = initUnorderedMap()
290+
let n = m.mapValues { v in v * 2 }
291+
expectEqual(n[1], 6)
292+
expectEqual(n[2], 4)
293+
expectEqual(n[3], 6)
294+
295+
let n2: UnorderedIntString = m.mapValues { v in std.string("\(v * 3)") }
296+
expectEqual(n2[1], std.string("9"))
297+
expectEqual(n2[2], std.string("6"))
298+
expectEqual(n2[3], std.string("9"))
299+
300+
let n3: Map = m.mapValues { v in v * 4 }
301+
expectEqual(n3[1], 12)
302+
expectEqual(n3[2], 8)
303+
expectEqual(n3[3], 12)
304+
}
305+
306+
StdMapTestSuite.test("Map.compactMapValues") {
307+
let m = Map([1: 1, 2: 2, 3: 3, 4: 4])
308+
let n = m.compactMapValues { v in v % 2 == 0 ? nil : v * 2 }
309+
expectEqual(n[1], 2)
310+
expectNil(n[2])
311+
expectEqual(n[3], 6)
312+
expectNil(n[4])
313+
314+
let n2: MapIntString = m.compactMapValues { v in v % 2 == 0 ? nil : std.string("\(v * 3)") }
315+
expectEqual(n2[1], std.string("3"))
316+
expectNil(n2[2])
317+
expectEqual(n2[3], std.string("9"))
318+
expectNil(n2[4])
319+
320+
let n3: UnorderedMap = m.compactMapValues { v in v % 2 == 0 ? nil : v * 4 }
321+
expectEqual(n3[1], 4)
322+
expectNil(n3[2])
323+
expectEqual(n3[3], 12)
324+
expectNil(n3[4])
325+
}
326+
327+
StdMapTestSuite.test("UnorderedMap.compactMapValues") {
328+
let m = UnorderedMap([1: 1, 2: 2, 3: 3, 4: 4])
329+
330+
let n = m.compactMapValues { v in v % 2 == 0 ? nil : v * 2 }
331+
expectEqual(n[1], 2)
332+
expectNil(n[2])
333+
expectEqual(n[3], 6)
334+
expectNil(n[4])
335+
336+
let n2: UnorderedIntString = m.compactMapValues { v in v % 2 == 0 ? nil : std.string("\(v * 3)") }
337+
expectEqual(n2[1], std.string("3"))
338+
expectNil(n2[2])
339+
expectEqual(n2[3], std.string("9"))
340+
expectNil(n2[4])
341+
342+
let n3: Map = m.compactMapValues { v in v % 2 == 0 ? nil : v * 4 }
343+
expectEqual(n3[1], 4)
344+
expectNil(n3[2])
345+
expectEqual(n3[3], 12)
346+
expectNil(n3[4])
347+
}
348+
270349
StdMapTestSuite.test("Map.filter") {
271350
var m = initMap()
272351
var n = initEmptyMap()

0 commit comments

Comments
 (0)