如何编写适配Array、Set和Dictionary的Swift Sequence扩展?
Hey there! Let's work through your two issues step by step to build an extension that plays nicely with all three collection types you mentioned.
Issue 1: Replacing the hardcoded variable with self
Your original code references a specific numbers variable, but in a protocol extension, you need to use self to refer to the current instance of the sequence. We also need to add a type constraint—since isMultiple(of:) is a method for integer types, we’ll restrict the extension to sequences whose elements conform to BinaryInteger.
Here’s the fixed base extension that works for Array and Set:
extension Sequence where Element: BinaryInteger { var isAllEven: Bool { self.allSatisfy { $0.isMultiple(of: 2) } } } // Test with Set let numberSet = Set([4, 8, 16]) print(numberSet.isAllEven) // Output: true // Test with Array let numberArray = [2, 4, 6] print(numberArray.isAllEven) // Output: true
Issue 2: Adapting for Dictionary
Dictionary’s Element type is a tuple (key: Key, value: Value), so we can’t reuse the exact same isAllEven property—we need to clarify whether we’re checking keys, values, or make the extension flexible enough for both.
Option 1: Add a dedicated property for Dictionary (check values)
If your goal is to verify all values in a Dictionary are even, extend Dictionary with a constrained property:
extension Dictionary where Value: BinaryInteger { var isAllValuesEven: Bool { self.values.allSatisfy { $0.isMultiple(of: 2) } } } // Test with Dictionary let numberDict = ["a": 2, "b": 4, "c": 6] print(numberDict.isAllValuesEven) // Output: true
Option 2: Build a flexible generic method
For a more versatile solution that works for all sequences (including Dictionary, where you can pick which part to check), use a generic method with key paths:
extension Sequence { func allElementsSatisfyEven<T: BinaryInteger>(_ keyPath: KeyPath<Element, T>) -> Bool { self.allSatisfy { $0[keyPath: keyPath].isMultiple(of: 2) } } } // Use with Array/Set let intSet = Set([4, 8, 16]) print(intSet.allElementsSatisfyEven(\.self)) // Output: true // Use with Dictionary (check values) let valueDict = ["x": 2, "y": 4] print(valueDict.allElementsSatisfyEven(\.value)) // Output: true // Use with Dictionary (check integer keys) let intKeyDict = [2: "apple", 4: "banana"] print(intKeyDict.allElementsSatisfyEven(\.key)) // Output: true
This approach lets you target any integer property of the sequence’s elements, making it perfect for Dictionary’s key-value tuples.
内容的提问来源于stack exchange,提问作者Swantewit

