<div dir="ltr"><div>To handle the case of duplicate keys, why not allow to pass in a &#39;combine&#39; function? This could default to a preconditionFailure to be consistent with the DictionaryLiteral behavior, but be overridden by the caller as needed.<br><br>extension Dictionary {<br>    /// Creates a dictionary with the keys and values in the given sequence.<br>   
 init&lt;S: SequenceType where S.Generator.Element == 
Generator.Element&gt;(_ sequence: S, combine: (existing: Value, other: 
Value) -&gt; Value = { preconditionFailure(&quot;Sequence contains duplicate 
keys&quot;); return $1 } ) {<br>        self.init()<br>        for (key, value) in sequence {<br>            if let existing = updateValue(value, forKey: key) {<br>                updateValue(combine(existing: existing, other: value), forKey: key)<br>            }<br>        }<br>    }<br>}<br><br><br></div>usage examples:<br><br><div><br>&gt; A brief draft is below... I had mostly written this up before I saw the thread and Gwendal&#39;s similar contribution -- happy to hear feedback and fold in comments/revisions!<br>&gt;<br>&gt; Nate<br>&gt;<br>&gt;<br>&gt; ---<br>&gt;<br>&gt;<br>&gt; Introduction<br>&gt;<br>&gt; The Dictionary type should allow initialization from a sequence of (Key, Value) tuples.<br>&gt;<br>&gt; Motivation<br>&gt;<br>&gt; Array and Set both have initializers that create a new instance from a sequence of elements. The Array initializer is useful for converting other sequences and collections to the &quot;standard&quot; collection type, but the Set initializer is essential for recovering set operations after performing any functional operations on a set. For example, filtering a set produces a collection without any kind of set operations available:<br>&gt;<br>&gt; let numberSet = Set(1 ... 100)<br>&gt; let fivesOnly = numberSet.lazy.filter { $0 % 5 == 0 }<br>&gt;<br>&gt; &quot;fivesOnly&quot; is a LazyFilterCollection&lt;Set&lt;Int&gt;&gt; instead of a Set -- sending that back through the Set sequence initializer restores the expected methods:<br>&gt;<br>&gt; let fivesOnlySet = Set(numberSet.lazy.filter { $0 % 5 == 0 })<br>&gt; fivesOnlySet.isSubsetOf(numberSet) // true<br>&gt;<br>&gt; Dictionary, on the other hand, has no such initializer, so a similar operation leaves no room except for building a mutable Dictionary via iteration or functional methods with dubious performance. These techniques also don&#39;t support type inference from the source sequence, increasing verbosity:<br>&gt;<br>&gt; var viaIteration: [String: Int] = [:]<br>&gt; for (key, value) in evenOnly {<br>&gt;     viaIteration[key] = value<br>&gt; }<br>&gt;<br>&gt; let viaFunction: [String: Int] = evenOnly.reduce([:]) { (cumulative, keyValue) in<br>&gt;     var mutableDictionary = cumulative<br>&gt;     mutableDictionary[keyValue.0] = keyValue.1<br>&gt;     return mutableDictionary<br>&gt; }<br>&gt;<br>&gt; Proposed solution<br>&gt;<br>&gt; The proposed solution would add an initializer to Dictionary that accepts any sequence of (Key, Value) tuple pairs, matching the Dictionary&#39;s element type when treated as a sequence:<br>&gt;<br>&gt; init&lt;S: SequenceType where S.Generator.Element == Generator.Element&gt;(_ sequence: S)<br>&gt;<br>&gt; Instead of the techniques for recovering a Dictionary shown above, the proposed initializer would allow a much cleaner syntax to be written:<br>&gt;<br>&gt; let viaProposed = Dictionary(evenOnly)<br>&gt;<br>&gt; Moreover, this new initializer would allow for some convenient uses that aren&#39;t currently possible.<br>&gt;<br>&gt; 👍🏼 Initializing from an array of tuples:<br>&gt;<br>&gt; let dictFromArray = Dictionary([(&quot;a&quot;, 1), (&quot;b&quot;, 2), (&quot;c&quot;, 3), (&quot;d&quot;, 4)])<br>&gt;<br>&gt; 👏🏼 Initializing from a DictionaryLiteral (the type, not an actual literal):<br>&gt;<br>&gt; let literal: DictionaryLiteral = [&quot;a&quot;: 1, &quot;b&quot;: 2, &quot;c&quot;: 3, &quot;d&quot;: 4]<br>&gt; let dictFromDL = Dictionary(literal)<br>&gt;<br>&gt; 🎉 Initializing from a pair of zipped sequences (examples abound):<br>&gt;<br>&gt; let letters = &quot;abcdefghij&quot;.characters.lazy.map { String($0) }<br>&gt; let dictFromZip = Dictionary(zip(letters, 1...10))<br>&gt; // [&quot;b&quot;: 2, &quot;a&quot;: 1, &quot;i&quot;: 9, &quot;j&quot;: 10, &quot;c&quot;: 3, &quot;e&quot;: 5, &quot;f&quot;: 6, &quot;g&quot;: 7, &quot;d&quot;: 4, &quot;h&quot;: 8]<br>&gt;<br>&gt; Potential pitfalls<br>&gt;<br>&gt; One caveat is that the new initializer doesn&#39;t prevent using a sequence with multiple identical keys. In such a case, the last key/value would &quot;win&quot; and exist in the dictionary. Such an initialization is a compile-time error with a dictionary literal, but succeeds under the new initializer:<br>&gt;<br>&gt; let _ = [&quot;z&quot;: 1, &quot;z&quot;: 2, &quot;z&quot;: 3, &quot;z&quot;: 4]<br>&gt; // fatal error: Dictionary literal contains duplicate keys<br>&gt; Dictionary([(&quot;z&quot;, 1), (&quot;z&quot;, 2), (&quot;z&quot;, 3), (&quot;z&quot;, 4)])<br>&gt; // [&quot;z&quot;: 4]<br>&gt;<br>&gt; This behavior is particularly troublesome when used in conjunction with a mapping operation that modifies a dictionary&#39;s keys, since dictionaries have no particular guaranteed order:<br>&gt;<br>&gt; let overlapping = Dictionary(dictFromArray.lazy.map { (_, value) in (&quot;z&quot;, value) })<br>&gt; // [&quot;z&quot;: ???]<br>&gt;<br>&gt; While a pitfall, this behavior is less a symptom of the proposed API and more an inherent problem with recovering a dictionary after modifying its keys. The current ways of rebuilding a dictionary (as shown above) are just as susceptible to silently dropping values. Moreover, the sequence-based initializer for Set exhibits the same behavior, though slightly less problematic in most cases:<br>&gt;<br>&gt; let dividedNumbers = Set(numberSet.map { $0 / 20 })<br>&gt; // {4, 5, 2, 0, 1, 3}<br>&gt;<br>&gt; Given the potential lossiness of the initializer, should it use a parameter name for the sequence? I would suggest not, to match the syntax of Array.init(_:) and Set.init(_:), but a parameter like &quot;collapsingKeys&quot; would make the risk clear to users.<br>&gt;<br>&gt; Detailed design<br>&gt;<br>&gt; The implementation is simple enough to show in the proposal:<br>&gt;<br>&gt; extension Dictionary {<br>&gt;     /// Creates a dictionary with the keys and values in the given sequence.<br>&gt;     init&lt;S: SequenceType where S.Generator.Element == Generator.Element&gt;(_ sequence: S) {<br>&gt;         self.init()<br>&gt;         for (key, value) in sequence {<br>&gt;             updateValue(value, forKey: key)<br>&gt;         }<br>&gt;     }<br>&gt; }<br>&gt;<br>&gt; (As part of the standard library, this could use the nativeUpdateValue method.)<br>&gt;<br>&gt; Impact on existing code<br>&gt;<br>&gt; As a new API, this will have no impact on existing code.<br>&gt;<br>&gt; Alternatives considered<br>&gt;<br>&gt; As suggested in the thread below, a method could be added to SequenceType that would build a dictionary. This approach seems less of a piece with the rest of the standard library, and overly verbose when used with a Dictionary that is only passing through filtering or mapping operations. I don&#39;t think the current protocol extension system could handle a passthrough case (i.e., something like &quot;extension SequenceType where Generator.Element == (Key, Value)&quot;).<br>&gt;<br>&gt; Alternately, the status quo could be maintained. Which would be sad.<br>&gt;<br>&gt;<br>&gt;<br>&gt;<br>&gt; &gt; On Jan 13, 2016, at 11:55 AM, Gwendal Roué via swift-evolution &lt;swift-evolution at <a href="http://swift.org">swift.org</a>&gt; wrote:<br>&gt; &gt;<br>&gt; &gt; Doesn’t Swift prefer initializers?<br>&gt; &gt;<br>&gt; &gt; So let’s build a Dictionary initializer that eats any sequence of (key, value) pairs:<br>&gt; &gt;<br>&gt; &gt; extension Dictionary {<br>&gt; &gt;     init&lt;S: SequenceType where S.Generator.Element == (Key, Value)&gt;(keyValueSequence s: S) {<br>&gt; &gt;         self.init()<br>&gt; &gt;         for (key, value) in s {<br>&gt; &gt;             self[key] = value<br>&gt; &gt;         }<br>&gt; &gt;     }<br>&gt; &gt; }<br>&gt; &gt;<br>&gt; &gt; do {<br>&gt; &gt;     // From array of (key, value) pairs<br>&gt; &gt;     let input = [(&quot;foo&quot;, 1), (&quot;bar&quot;, 2)]<br>&gt; &gt;     let d = Dictionary(keyValueSequence: input)<br>&gt; &gt;     print(d)<br>&gt; &gt; }<br>&gt; &gt; do {<br>&gt; &gt;     // From another dictionary<br>&gt; &gt;     let input = [1: &quot;foo&quot;, 2: &quot;bar&quot;]<br>&gt; &gt;     let d = Dictionary(keyValueSequence: input)<br>&gt; &gt;     print(d)<br>&gt; &gt; }<br>&gt; &gt; do {<br>&gt; &gt;     // Reverse key and values<br>&gt; &gt;     let input = [1: &quot;foo&quot;, 2: &quot;bar&quot;]<br>&gt; &gt;     let d = Dictionary(keyValueSequence: input.map { ($1, $0) })<br>&gt; &gt;     print(d)<br>&gt; &gt; }<br>&gt; &gt;<br>&gt; &gt; Gwendal<br>&gt; &gt;<br>&gt; &gt;&gt; Le 13 janv. 2016 à 18:41, Thorsten Seitz via swift-evolution &lt;swift-evolution at <a href="http://swift.org">swift.org</a> &lt;mailto:<a href="mailto:swift-evolution">swift-evolution</a> at <a href="http://swift.org">swift.org</a>&gt;&gt; a écrit :<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; I&#39;d prefer &quot;mapToDict&quot; otherwise it sounds like a dictionary gets mapped, at least for me.<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; -Thorsten<br>&gt; &gt;&gt;<br>&gt; &gt;&gt;&gt; Am 13.01.2016 um 17:13 schrieb Kenny Leung via swift-evolution &lt;swift-evolution at <a href="http://swift.org">swift.org</a> &lt;mailto:<a href="mailto:swift-evolution">swift-evolution</a> at <a href="http://swift.org">swift.org</a>&gt;&gt;:<br>&gt; &gt;&gt;&gt;<br>&gt; &gt;&gt;&gt; This solution looks great! How do you feel about “mapDict”?<br>&gt; &gt;&gt;&gt;<br>&gt; &gt;&gt;&gt; -Kenny<br>&gt; &gt;&gt;&gt;<br>&gt; &gt;&gt;&gt;<br>&gt; &gt;&gt;&gt;&gt;&gt; On Jan 12, 2016, at 10:28 AM, Craig Cruden &lt;ccruden at <a href="http://novafore.com">novafore.com</a> &lt;mailto:<a href="mailto:ccruden">ccruden</a> at <a href="http://novafore.com">novafore.com</a>&gt;&gt; wrote:<br>&gt; &gt;&gt;&gt;&gt;&gt;<br>&gt; &gt;&gt;&gt;&gt;&gt;<br>&gt; &gt;&gt;&gt;&gt;&gt;<br>&gt; &gt;&gt;&gt;&gt;&gt; I named the method(s) „toDict“ instead of „map“ because map normally returns a collection which is either the same as the receiver or a simple one.<br>&gt; &gt;&gt;&gt;&gt;&gt; The second version is more general and allows to do things like<br>&gt; &gt;&gt;&gt;&gt;&gt;<br>&gt; &gt;&gt;&gt;&gt;&gt; let dict = [&quot;Tom&quot;, &quot;Dick&quot;, &quot;Harry&quot;].enumerate().toDict { (index, value) in (index + 1, value) }<br>&gt; &gt;&gt;&gt;&gt;<br>&gt; &gt;&gt;&gt;&gt; Map would probably be a more correct mathematically speaking — but it would be inconsistent with the naming convention already chosen for Swift.  So for Swift - toDict (or toDictionary) would be the best choice.</div></div>