Skip to content

Add filter method for ordered and unordered map #67501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Oct 5, 2023
Merged
24 changes: 23 additions & 1 deletion stdlib/public/Cxx/CxxDictionary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ public protocol CxxDictionary<Key, Value> {
associatedtype Size: BinaryInteger
associatedtype InsertionResult

init()

/// Do not implement this function manually in Swift.
func __findUnsafe(_ key: Key) -> RawIterator

/// Do not implement this function manually in Swift.
mutating func __findMutatingUnsafe(_ key: Key) -> RawMutableIterator

Expand All @@ -39,6 +40,9 @@ public protocol CxxDictionary<Key, Value> {
@discardableResult
mutating func erase(_ key: Key) -> Size

/// Do not implement this function manually in Swift.
func __beginUnsafe() -> RawIterator

/// Do not implement this function manually in Swift.
func __endUnsafe() -> RawIterator

Expand Down Expand Up @@ -72,4 +76,22 @@ extension CxxDictionary {
}
}
}

public func filter(_ isIncluded: (_ key: Key, _ value: Value) throws -> Bool) rethrows -> Self {
var filteredDictionary = Self.init()
var iterator = __beginUnsafe()
let endIterator = __endUnsafe()

while iterator != endIterator {
let pair = iterator.pointee

if try isIncluded(pair.first, pair.second) {
filteredDictionary.__insertUnsafe(pair)
}

iterator = iterator.successor()
}

return filteredDictionary
}
}
4 changes: 3 additions & 1 deletion test/Interop/Cxx/stdlib/Inputs/std-map.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#define TEST_INTEROP_CXX_STDLIB_INPUTS_STD_MAP_H

#include <map>
#include <unordered_map>
#include <string>
#include <unordered_map>

using Map = std::map<int, int>;
using MapStrings = std::map<std::string, std::string>;
Expand All @@ -12,5 +12,7 @@ using UnorderedMap = std::unordered_map<int, int>;

inline Map initMap() { return {{1, 3}, {2, 2}, {3, 3}}; }
inline UnorderedMap initUnorderedMap() { return {{1, 3}, {3, 3}, {2, 2}}; }
inline Map initEmptyMap() { return {}; }
inline UnorderedMap initEmptyUnorderedMap() { return {}; }

#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_MAP_H
32 changes: 32 additions & 0 deletions test/Interop/Cxx/stdlib/use-std-map.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,38 @@ StdMapTestSuite.test("UnorderedMap.subscript") {
expectNil(m[-1])
}

StdMapTestSuite.test("Map.filter") {
var m = initMap()
var n = initEmptyMap()

expectNotNil(m[1])
expectEqual(n.size(), 0)

m = m.filter { k, v in k != 1 }
n = n.filter { k, v in false }

expectNil(m[1])
expectEqual(m[2], 2)
expectEqual(m[3], 3)
expectTrue(n.empty())
}

StdMapTestSuite.test("UnorderedMap.filter") {
var m = initUnorderedMap()
var n = initEmptyUnorderedMap()

expectNotNil(m[1])
expectEqual(n.size(), 0)

m = m.filter { k, v in k != 1 }
n = n.filter { k, v in false }

expectNil(m[1])
expectEqual(m[2], 2)
expectEqual(m[3], 3)
expectTrue(n.empty())
}

StdMapTestSuite.test("Map.erase") {
var m = initMap()
expectNotNil(m[1])
Expand Down