mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
165 lines
6.3 KiB
Swift
165 lines
6.3 KiB
Swift
//===--- KeyValuePairs.swift ----------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// A lightweight collection of key-value pairs.
|
|
///
|
|
/// Use a `KeyValuePairs` instance when you need an ordered collection of
|
|
/// key-value pairs and don't require the fast key lookup that the
|
|
/// `Dictionary` type provides. Unlike key-value pairs in a true dictionary,
|
|
/// neither the key nor the value of a `KeyValuePairs` instance must
|
|
/// conform to the `Hashable` protocol.
|
|
///
|
|
/// You initialize a `KeyValuePairs` instance using a Swift dictionary
|
|
/// literal. Besides maintaining the order of the original dictionary literal,
|
|
/// `KeyValuePairs` also allows duplicates keys. For example:
|
|
///
|
|
/// let recordTimes: KeyValuePairs = ["Florence Griffith-Joyner": 10.49,
|
|
/// "Evelyn Ashford": 10.76,
|
|
/// "Evelyn Ashford": 10.79,
|
|
/// "Marlies Gohr": 10.81]
|
|
/// print(recordTimes.first!)
|
|
/// // Prints "(key: "Florence Griffith-Joyner", value: 10.49)"
|
|
///
|
|
/// Some operations that are efficient on a dictionary are slower when using
|
|
/// `KeyValuePairs`. In particular, to find the value matching a key, you
|
|
/// must search through every element of the collection. The call to
|
|
/// `firstIndex(where:)` in the following example must traverse the whole
|
|
/// collection to find the element that matches the predicate:
|
|
///
|
|
/// let runner = "Marlies Gohr"
|
|
/// if let index = recordTimes.firstIndex(where: { $0.0 == runner }) {
|
|
/// let time = recordTimes[index].1
|
|
/// print("\(runner) set a 100m record of \(time) seconds.")
|
|
/// } else {
|
|
/// print("\(runner) couldn't be found in the records.")
|
|
/// }
|
|
/// // Prints "Marlies Gohr set a 100m record of 10.81 seconds."
|
|
///
|
|
/// Key-Value Pairs as a Function Parameter
|
|
/// ---------------------------------------
|
|
///
|
|
/// When calling a function with a `KeyValuePairs` parameter, you can pass
|
|
/// a Swift dictionary literal without causing a `Dictionary` to be created.
|
|
/// This capability can be especially important when the order of elements in
|
|
/// the literal is significant.
|
|
///
|
|
/// For example, you could create an `IntPairs` structure that holds a list of
|
|
/// two-integer tuples and use an initializer that accepts a
|
|
/// `KeyValuePairs` instance.
|
|
///
|
|
/// struct IntPairs {
|
|
/// var elements: [(Int, Int)]
|
|
///
|
|
/// init(_ elements: KeyValuePairs<Int, Int>) {
|
|
/// self.elements = Array(elements)
|
|
/// }
|
|
/// }
|
|
///
|
|
/// When you're ready to create a new `IntPairs` instance, use a dictionary
|
|
/// literal as the parameter to the `IntPairs` initializer. The
|
|
/// `KeyValuePairs` instance preserves the order of the elements as
|
|
/// passed.
|
|
///
|
|
/// let pairs = IntPairs([1: 2, 1: 1, 3: 4, 2: 1])
|
|
/// print(pairs.elements)
|
|
/// // Prints "[(1, 2), (1, 1), (3, 4), (2, 1)]"
|
|
@frozen // trivial-implementation
|
|
public struct KeyValuePairs<Key, Value>: ExpressibleByDictionaryLiteral {
|
|
@usableFromInline // trivial-implementation
|
|
internal let _elements: [(Key, Value)]
|
|
|
|
/// Creates a new `KeyValuePairs` instance from the given dictionary
|
|
/// literal.
|
|
///
|
|
/// The order of the key-value pairs is kept intact in the resulting
|
|
/// `KeyValuePairs` instance.
|
|
@inlinable // trivial-implementation
|
|
public init(dictionaryLiteral elements: (Key, Value)...) {
|
|
self._elements = elements
|
|
}
|
|
}
|
|
|
|
/// `Collection` conformance that allows `KeyValuePairs` to
|
|
/// interoperate with the rest of the standard library.
|
|
extension KeyValuePairs: RandomAccessCollection {
|
|
/// The element type of a `KeyValuePairs`: a tuple containing an
|
|
/// individual key-value pair.
|
|
public typealias Element = (key: Key, value: Value)
|
|
public typealias Index = Int
|
|
public typealias Indices = Range<Int>
|
|
public typealias SubSequence = Slice<KeyValuePairs>
|
|
|
|
/// The position of the first element in a nonempty collection.
|
|
///
|
|
/// If the `KeyValuePairs` instance is empty, `startIndex` is equal to
|
|
/// `endIndex`.
|
|
@inlinable // trivial-implementation
|
|
public var startIndex: Index { return 0 }
|
|
|
|
/// The collection's "past the end" position---that is, the position one
|
|
/// greater than the last valid subscript argument.
|
|
///
|
|
/// If the `KeyValuePairs` instance is empty, `endIndex` is equal to
|
|
/// `startIndex`.
|
|
@inlinable // trivial-implementation
|
|
public var endIndex: Index { return _elements.endIndex }
|
|
|
|
/// Accesses the element at the specified position.
|
|
///
|
|
/// - Parameter position: The position of the element to access. `position`
|
|
/// must be a valid index of the collection that is not equal to the
|
|
/// `endIndex` property.
|
|
/// - Returns: The key-value pair at position `position`.
|
|
@inlinable // trivial-implementation
|
|
public subscript(position: Index) -> Element {
|
|
return _elements[position]
|
|
}
|
|
}
|
|
|
|
@available(SwiftCompatibilitySpan 5.0, *)
|
|
@_originallyDefinedIn(module: "Swift;CompatibilitySpan", SwiftCompatibilitySpan 6.2)
|
|
extension KeyValuePairs {
|
|
@available(SwiftCompatibilitySpan 5.0, *)
|
|
@_alwaysEmitIntoClient
|
|
public var span: Span<Element> {
|
|
@lifetime(borrow self)
|
|
get {
|
|
let rp = unsafe UnsafeRawPointer(_elements._buffer.firstElementAddress)
|
|
let span = unsafe Span(
|
|
_unsafeStart: unsafe rp.assumingMemoryBound(to: Element.self),
|
|
count: _elements.count
|
|
)
|
|
return unsafe _overrideLifetime(span, borrowing: self)
|
|
}
|
|
}
|
|
}
|
|
|
|
@_unavailableInEmbedded
|
|
extension KeyValuePairs: CustomStringConvertible {
|
|
/// A string that represents the contents of the dictionary.
|
|
public var description: String {
|
|
return _makeKeyValuePairDescription()
|
|
}
|
|
}
|
|
|
|
@_unavailableInEmbedded
|
|
extension KeyValuePairs: CustomDebugStringConvertible {
|
|
/// A string that represents the contents of the dictionary, suitable for
|
|
/// debugging.
|
|
public var debugDescription: String {
|
|
return _makeKeyValuePairDescription()
|
|
}
|
|
}
|
|
|
|
extension KeyValuePairs: Sendable
|
|
where Key: Sendable, Value: Sendable { }
|