Skip to content

Commit f271db2

Browse files
authored
Merge pull request #83429 from CrazyFanFan/feature/cxx_map_mapvalues_and_compactmapvalues
Adds `mapValues` and `compactMapValues` to CxxDictionary:
2 parents affc8c1 + 4426912 commit f271db2

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
@@ -304,6 +304,85 @@ StdMapTestSuite.test("UnorderedMap.subscript(:default:)") {
304304
expectEqual(m[-5, default: 555], 555)
305305
}
306306

307+
StdMapTestSuite.test("Map.mapValues") {
308+
let m = initMap()
309+
let n = m.mapValues { v in v * 2 }
310+
expectEqual(n[1], 6)
311+
expectEqual(n[2], 4)
312+
expectEqual(n[3], 6)
313+
314+
let n2: MapIntString = m.mapValues { v in std.string("\(v * 3)") }
315+
expectEqual(n2[1], std.string("9"))
316+
expectEqual(n2[2], std.string("6"))
317+
expectEqual(n2[3], std.string("9"))
318+
319+
let n3: UnorderedMap = m.mapValues { v in v * 4 }
320+
expectEqual(n3[1], 12)
321+
expectEqual(n3[2], 8)
322+
expectEqual(n3[3], 12)
323+
}
324+
325+
StdMapTestSuite.test("UnorderedMap.mapValues") {
326+
let m = initUnorderedMap()
327+
let n = m.mapValues { v in v * 2 }
328+
expectEqual(n[1], 6)
329+
expectEqual(n[2], 4)
330+
expectEqual(n[3], 6)
331+
332+
let n2: UnorderedIntString = m.mapValues { v in std.string("\(v * 3)") }
333+
expectEqual(n2[1], std.string("9"))
334+
expectEqual(n2[2], std.string("6"))
335+
expectEqual(n2[3], std.string("9"))
336+
337+
let n3: Map = m.mapValues { v in v * 4 }
338+
expectEqual(n3[1], 12)
339+
expectEqual(n3[2], 8)
340+
expectEqual(n3[3], 12)
341+
}
342+
343+
StdMapTestSuite.test("Map.compactMapValues") {
344+
let m = Map([1: 1, 2: 2, 3: 3, 4: 4])
345+
let n = m.compactMapValues { v in v % 2 == 0 ? nil : v * 2 }
346+
expectEqual(n[1], 2)
347+
expectNil(n[2])
348+
expectEqual(n[3], 6)
349+
expectNil(n[4])
350+
351+
let n2: MapIntString = m.compactMapValues { v in v % 2 == 0 ? nil : std.string("\(v * 3)") }
352+
expectEqual(n2[1], std.string("3"))
353+
expectNil(n2[2])
354+
expectEqual(n2[3], std.string("9"))
355+
expectNil(n2[4])
356+
357+
let n3: UnorderedMap = m.compactMapValues { v in v % 2 == 0 ? nil : v * 4 }
358+
expectEqual(n3[1], 4)
359+
expectNil(n3[2])
360+
expectEqual(n3[3], 12)
361+
expectNil(n3[4])
362+
}
363+
364+
StdMapTestSuite.test("UnorderedMap.compactMapValues") {
365+
let m = UnorderedMap([1: 1, 2: 2, 3: 3, 4: 4])
366+
367+
let n = m.compactMapValues { v in v % 2 == 0 ? nil : v * 2 }
368+
expectEqual(n[1], 2)
369+
expectNil(n[2])
370+
expectEqual(n[3], 6)
371+
expectNil(n[4])
372+
373+
let n2: UnorderedIntString = m.compactMapValues { v in v % 2 == 0 ? nil : std.string("\(v * 3)") }
374+
expectEqual(n2[1], std.string("3"))
375+
expectNil(n2[2])
376+
expectEqual(n2[3], std.string("9"))
377+
expectNil(n2[4])
378+
379+
let n3: Map = m.compactMapValues { v in v % 2 == 0 ? nil : v * 4 }
380+
expectEqual(n3[1], 4)
381+
expectNil(n3[2])
382+
expectEqual(n3[3], 12)
383+
expectNil(n3[4])
384+
}
385+
307386
StdMapTestSuite.test("Map.filter") {
308387
var m = initMap()
309388
var n = initEmptyMap()

0 commit comments

Comments
 (0)