<div dir="ltr">I don&#39;t think I&#39;ve ever called map on a dictionary in production code, only a mapValue function like this thread discusses. When do we actually want to call map on a dictionary? I feel like mapValue should be the default.<br><br>
<p style="margin:0px;line-height:normal">I&#39;m wondering if <font face="Menlo"><span style="font-size:11px">`Dictionary&lt;String,Int&gt;.Element`</span></font>should be <span style="font-family:Menlo;font-size:11px">`Value`, </span>instead of <font face="Menlo"><span style="font-size:11px">`(Key,Value)`</span></font>.</p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span style=""></span><br></p>
With an array you can do this:<div><br>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)">for</span><span style=""> (key, value) </span><span style="color:rgb(187,44,162)">in</span><span style=""> [</span><span style="color:rgb(209,47,27)">&quot;a&quot;</span><span style="">, </span><span style="color:rgb(209,47,27)">&quot;b&quot;</span><span style="">, </span><span style="color:rgb(209,47,27)">&quot;c&quot;</span><span style="">].</span><span style="color:rgb(61,29,129)">enumerate</span><span style="">() {</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="">    </span><span style="color:rgb(61,29,129)">print</span><span style="">(key, value) </span><span style="color:rgb(0,132,0)">// 0 a, 1 b, 2 c</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="">}</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span style=""></span><br></p>
Shouldn&#39;t the equivalent for a dictionary be this?
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span style=""></span><br></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)">for</span><span style=""> (key, value) </span><span style="color:rgb(187,44,162)">in</span><span style=""> [</span><span style="color:rgb(209,47,27)">&quot;a&quot;</span><span style="">: </span><span style="color:rgb(39,42,216)">0</span><span style="">, </span><span style="color:rgb(209,47,27)">&quot;b&quot;</span><span style="">: </span><span style="color:rgb(39,42,216)">1</span><span style="">, </span><span style="color:rgb(209,47,27)">&quot;c&quot;</span><span style="">: </span><span style="color:rgb(39,42,216)">2</span><span style="">].</span><span style="color:rgb(61,29,129)">enumerate</span><span style="">() {</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="">    </span><span style="color:rgb(61,29,129)">print</span><span style="">(key, value) </span><span style="color:rgb(0,132,0)">// a 0, b 1, c 2</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="">}</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span style=""></span><br></p>
Not this:
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span style=""></span><br></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)">for</span><span style=""> (key, value) </span><span style="color:rgb(187,44,162)">in</span><span style=""> [</span><span style="color:rgb(209,47,27)">&quot;a&quot;</span><span style="">: </span><span style="color:rgb(39,42,216)">0</span><span style="">, </span><span style="color:rgb(209,47,27)">&quot;b&quot;</span><span style="">: </span><span style="color:rgb(39,42,216)">1</span><span style="">, </span><span style="color:rgb(209,47,27)">&quot;c&quot;</span><span style="">: </span><span style="color:rgb(39,42,216)">2</span><span style="">] {</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="">    </span><span style="color:rgb(61,29,129)">print</span><span style="">(key, value) </span><span style="color:rgb(0,132,0)">// a 0, b 1, c 2</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="">}</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style=""><br></span></p>Presumably the old syntax would produce only values:<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)">for</span> value <span style="color:rgb(187,44,162)">in</span> [<span style="color:rgb(209,47,27)">&quot;a&quot;</span>: <span style="color:rgb(39,42,216)">0</span>, <span style="color:rgb(209,47,27)">&quot;b&quot;</span>: <span style="color:rgb(39,42,216)">1</span>, <span style="color:rgb(209,47,27)">&quot;c&quot;</span>: <span style="color:rgb(39,42,216)">2</span>] {</p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">    <span style="color:rgb(61,29,129)">print</span>(value) <span style="color:rgb(0,132,0)">// 0, 1, 2</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">}</p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><br></p>You can still iterate the keys like this:<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><br></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)">for</span> key <span style="color:rgb(187,44,162)">in</span> [<span style="color:rgb(209,47,27)">&quot;a&quot;</span>: <span style="color:rgb(39,42,216)">0</span>, <span style="color:rgb(209,47,27)">&quot;b&quot;</span>: <span style="color:rgb(39,42,216)">1</span>, <span style="color:rgb(209,47,27)">&quot;c&quot;</span>: <span style="color:rgb(39,42,216)">2</span>].keys {</p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">    <span style="color:rgb(61,29,129)">print</span>(key) <span style="color:rgb(0,132,0)">// a, b, c</span></p><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">}</p><div><br></div>I think I understand the reasoning for Dictionary the way it is, but I think it only provides consistency to the implementation, not the interface.</div><div><br></div><div>The result of all this being that Dictionary is more consistent (IMO), and map would work on the values of all collection types, not a mix of values and key/value pairs.</div><div><br></div><div>What do you think?<br><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style=""><br></span></p></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Apr 14, 2016 at 9:07 AM, Dave Abrahams via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
on Wed Apr 13 2016, Nate Cook &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br>
<br>
&gt;     On Apr 13, 2016, at 12:02 PM, Jacob Bandes-Storch via swift-evolution<br>
&gt;     &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br>
&gt;<br>
&gt;     To adhere to the API Design Guidelines, I think it should be named<br>
&gt;     &quot;mappingValues&quot;, right?<br>
&gt;<br>
&gt;     On Wed, Apr 13, 2016 at 4:23 AM, Vladimir.S via swift-evolution<br>
&gt;     &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br>
&gt;<br>
&gt;     As for mapKeys and many values into a single key. I believe we should have a<br>
&gt;         choice - do we expect multiply values for the same key or not. Just like<br>
&gt;         &quot;+&quot; and integer overflow : by default it raises the error, but if &quot;&amp;+&quot; -<br>
&gt;         we expect the overflow. I can imagine situations when it is ok for me to<br>
&gt;         have different values for the same key(if I don&#39;t care which of values<br>
&gt;         should be for that key in result dictionary).<br>
&gt;         So my proposal is some additional mapKey(allowMultiplyValues: true)<br>
&gt;         {...} or in any other form/name.<br>
&gt;<br>
&gt; There&#39;s a proposal (awaiting merging) to add Dictionary initializers and methods<br>
&gt; that work with key/value pairs. These provide different ways of dealing with the<br>
&gt; duplicate key issue after a call to the regular Collection.map method.<br>
&gt;<br>
&gt;     <a href="https://github.com/natecook1000/swift-evolution/blob/natecook-dictionary-merge/proposals/0000-add-sequence-based-init-and-merge-to-dictionary.md" rel="noreferrer" target="_blank">https://github.com/natecook1000/swift-evolution/blob/natecook-dictionary-merge/proposals/0000-add-sequence-based-init-and-merge-to-dictionary.md</a><br>
<br>
</span>Ah, yes, that reminds me of your answer to the question about whether we<br>
need a “uniquingKeys” label on that init(), which IMO is a good one: no,<br>
we don&#39;t need it, because the one without the label traps on duplicate<br>
keys.<br>
<span class=""><br>
&gt; I&#39;d be interested in a `mapValues` or `transformValues` method that would modify<br>
&gt; values in place while leaving keys alone.<br>
<br>
</span>Is that enough of an improvement over<br>
<br>
   Dictionary(d.lazy.map { (k,v) in (k, transform(v)) })<br>
<br>
(once we get that initializer) to make it worth expanding the Dictionary<br>
API?<br>
<span class=""><br>
&gt; Another useful method (that could be used to build mapValues more efficiently)<br>
&gt; would be `Dictionary.updateValue(value: Value, at index: DictionaryIndex)`, so<br>
&gt; you could write:<br>
&gt;<br>
&gt; var dict = [&quot;a&quot;: 1, &quot;b&quot;: 2, &quot;c&quot;: 3]<br>
&gt; if let i = dict.index(where: { $0.value == 3 }) {<br>
&gt; dict.updateValue(100, at: i)<br>
&gt; }<br>
&gt; // dict == [&quot;a&quot;: 1, &quot;b&quot;: 2, &quot;c&quot;: 100]<br>
<br>
</span>Indeed it would!<br>
<div class="HOEnZb"><div class="h5"><br>
&gt; -Nate<br>
&gt;<br>
&gt;         On 13.04.2016 13:38, Ross O&#39;Brien via swift-evolution wrote:<br>
&gt;<br>
&gt;         +1 on mapValues.<br>
&gt;<br>
&gt;             DictionaryLiteral already throws an exception if it includes<br>
&gt;             duplicate<br>
&gt;             keys, so I&#39;d expect mapKeys to throw an error if multiple source<br>
&gt;             keys<br>
&gt;             mapped to the same destination key.<br>
&gt;<br>
&gt;             On Wed, Apr 13, 2016 at 11:28 AM, Miguel Angel Quinones via<br>
&gt;             swift-evolution<br>
&gt;             &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt;             &lt;mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt;&gt;<br>
&gt;             wrote:<br>
&gt;<br>
&gt;             I&#39;m +1 for adding mapValues. Very useful functionality and trivial<br>
&gt;             to<br>
&gt;             implement.<br>
&gt;<br>
&gt;             &gt; &gt; I.e. I suggest to implement and mapKeys() also. It could be also<br>
&gt;             useful in some situations.<br>
&gt;             &gt; `mapKeys` is much more dangerous, because you could end up mapping<br>
&gt;             many values into a single key. You kind of need to combine the<br>
&gt;             values somehow. Perhaps:<br>
&gt;             &gt;<br>
&gt;             &gt; extension Dictionary {<br>
&gt;             &gt; func mapValues__(_ valueTransform: @noescape Value throws<br>
&gt;             -&gt;OutValue) rethrows -&gt;[Key: OutValue] { … }<br>
&gt;             &gt;<br>
&gt;             &gt; func mapKeys__(_ keyTransform: @noescape Key throws -&gt;OutKey)<br>
&gt;             rethrows -&gt;[OutKey: [Value]] { … }<br>
&gt;             &gt;<br>
&gt;             &gt; // Possibly flatMap variants, too?<br>
&gt;             &gt; }<br>
&gt;             &gt;<br>
&gt;             &gt; extension Dictionary where Value: Sequence {<br>
&gt;             &gt; func reduceValues__(_ initial: OutValue, combine: @noescape<br>
&gt;             (OutValue, Value.Iterator.Element) throws -&gt;OutValue) rethrows -&gt;<br>
&gt;             [Key:<br>
&gt;             OutValue] {<br>
&gt;             &gt; return mapValues { $0.reduce(initial, combine: combine) }<br>
&gt;             &gt; }<br>
&gt;             &gt; }<br>
&gt;             &gt;<br>
&gt;             &gt; Which you would end up using like this:<br>
&gt;             &gt;<br>
&gt;             &gt; let wordFrequencies: [String: Int] = …<br>
&gt;             &gt; let firstLetterFrequencies: [Character: Int] =<br>
&gt;             wordFrequencies.mapKeys { $0.characters.first! }.reduceValues(0,<br>
&gt;             combine: +)<br>
&gt;             &gt;<br>
&gt;             &gt; --<br>
&gt;             &gt; Brent Royal-Gordon<br>
&gt;             &gt; Architechies<br>
&gt;             &gt;<br>
&gt;             &gt;<br>
&gt;             &gt;<br>
&gt;             &gt;______<br>
&gt;<br>
&gt;             --<br>
&gt;             Miguel Angel Quinones<br>
&gt;<br>
&gt;             _______________________________________________<br>
&gt;             swift-evolution mailing list<br>
&gt;             <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt;             &lt;mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt;<br>
&gt;             <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;<br>
&gt;             _______________________________________________<br>
&gt;             swift-evolution mailing list<br>
&gt;             <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt;             <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;<br>
&gt;         _______________________________________________<br>
&gt;         swift-evolution mailing list<br>
&gt;         <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt;         <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;<br>
&gt;     _______________________________________________<br>
&gt;     swift-evolution mailing list<br>
&gt;     <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt;     <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; swift-evolution mailing list<br>
&gt; <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br>
</div></div><span class="HOEnZb"><font color="#888888">--<br>
Dave<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</div></div></blockquote></div><br></div>