<div dir="ltr">FWIW: In cases like this, just remember call &quot;<span class="s1">.</span><span class="s2">reverse</span><span class="s1">()</span>&quot; and remove from the back.<div><br></div><div><div>var array = [ &quot;&quot;, &quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;&quot;, &quot;d&quot; ]</div><div>for (index, element) in array.enumerate().reverse() {</div><div>    if element == &quot;&quot; {</div><div>        array.removeAtIndex(index)</div><div>    }</div><div>}</div><div>print(array) // [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;]</div><div><br></div><div>zip is useful when we have ArraySlice as has been said before:<br></div></div><div><br></div><div><div>var array = [ &quot;&quot;, &quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;&quot;, &quot;d&quot;, &quot;&quot;, &quot;e&quot;, &quot;&quot; , &quot;f&quot;, &quot;g&quot;, &quot;&quot;]</div><div>var secondHalf = array[array.count/2..&lt;array.count]</div><div>print(secondHalf) // [&quot;&quot;, &quot;e&quot;, &quot;&quot;, &quot;f&quot;, &quot;g&quot;, &quot;&quot;]</div>







<div>for (index, element) in zip(secondHalf.indices, secondHalf).reverse() {</div><div>    if element == &quot;&quot; {</div><div>        secondHalf.removeAtIndex(index)</div><div>    }</div><div>}</div><div><br></div><div>print(secondHalf) // [&quot;e&quot;, &quot;f&quot;, &quot;g&quot;]</div><div><br></div><div>Anyway, it would not be correct to &quot;.enumerate()&quot; returns (Index, Element) instead of (n, Element)?<br></div><div><br></div><div>I believe that the current behavior was thought when Slices had indices starting with zero.<br></div><div><b><br></b></div>







<div class="gmail_quote"><div dir="ltr">Em ter, 29 de dez de 2015 às 00:30, Dany St-Amant via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; escreveu:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><br></div><div>The original example contains a bug which is present on all looping version/alternative due to the mutating nature of the array. Using the zip implementation:</div><div><br></div><div></div></div><div style="word-wrap:break-word"><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#bb2ca2">var</span> array = [ <span style="color:#d12f1b">&quot;&quot;</span>, <span style="color:#d12f1b">&quot;a&quot;</span>, <span style="color:#d12f1b">&quot;b&quot;</span>, <span style="color:#d12f1b">&quot;c&quot;</span>, <span style="color:#d12f1b">&quot;&quot;</span>, <span style="color:#d12f1b">&quot;d&quot;</span> ]</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#bb2ca2">var</span> secondHalf = <span style="color:#4f8187">array</span>[<span style="color:#4f8187">array</span>.<span style="color:#703daa">count</span>/<span style="color:#272ad8">2</span>..&lt;<span style="color:#4f8187">array</span>.<span style="color:#703daa">count</span>]</div></div></div><div style="word-wrap:break-word"><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:#bb2ca2">for</span> (index, element) <span style="color:#bb2ca2">in</span> <span style="color:#3d1d81">zip</span>(<span style="color:#4f8187">secondHalf</span>.<span style="color:#703daa">indices</span>, <span style="color:#4f8187">secondHalf</span>) {</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">    <span style="color:#bb2ca2">if</span> element == <span style="color:#d12f1b">&quot;&quot;</span> {</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">        <span style="color:#4f8187">secondHalf</span>.<span style="color:#3d1d81">removeAtIndex</span>(index)</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">    }</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo">}</div></div><div><br></div><div>The variable index cycles through 3,4 and 5; but in order to be able to remove the right element beyond the first removal, the variable index should have cycled through 3, 4 and 4 (as some elements got shifted after the first mutation). Mutating the array/list which one loops over is a risky business and is a nice source of bugs (including infinite loop). If this (Index, Element) is further investigated, it should consider that one may also want to do a insert(:atIndex:), and may expect the (Index, Element) to have proper Index but only for the original Element.</div></div><div style="word-wrap:break-word"><div><br></div><div>Dany St-Amant</div></div><div style="word-wrap:break-word"><div><br></div><div><br></div><div><blockquote type="cite"><div>Le 28 déc. 2015 à 01:06, Kevin Ballard via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; a écrit :</div><br><div>




<div><div>What you&#39;re asking for can already be done with `zip(col.indices, col)`. And in my experience the need for this sort of thing is rare enough that there&#39;s no need to have a dedicated property for it in the stdlib. The few times that I&#39;ve needed this sort of thing, I&#39;ve always just said<br></div>
<div> </div>
<div>for index in col.indices {<br></div>
<div>    let elt = col[index]<br></div>
<div>    // ...<br></div>
<div>}<br></div>
<div> </div>
<div>and that&#39;s pretty simple. But if I ever did need to map it, I&#39;d just use the aforementioned zip() expression.<br></div>
<div> </div>
<div>-Kevin Ballard<br></div>
<div> </div>
<div>On Sun, Dec 27, 2015, at 12:08 AM, Patrick Pijnappel via swift-evolution wrote:<br></div>
<blockquote type="cite"><div dir="ltr"><div>-- Introduction<br></div>
<div> </div>
<div>There should be a property on CollectionType that returns a sequence of (Index, Element) tuples.<br></div>
<div>Currently <span style="font-family:monospace,monospace">enumerate()</span> is often used instead, but it is not well suited to the task and can lead to bugs.<br></div>
<div> </div>
<div> </div>
<div> </div>
<div>-- Motivation<br></div>
<div> </div>
<div>Using <span style="font-family:monospace,monospace">enumerate()</span> instead of an <span style="font-family:monospace,&#39; monospace&#39;">(Index, Element)</span> sequence has two main problems.<br></div>
<div>Both arise because <span style="font-family:monospace,monospace">enumerate()</span> returns a sequence of <span style="font-family:monospace,&#39; monospace&#39;">(n, Element)</span> tuples,<br></div>
<div>where n is the element *number*, instead of a sequence of <span style="font-family:monospace,&#39; monospace&#39;">(Index, Element)</span>.<br></div>
<div> </div>
<div>1) It doesn&#39;t work for collections not indexed by integers.<br></div>
<div> </div>
<div>2) It doesn&#39;t do what you might expect in some cases, as indices do not always start at 0.<br></div>
<div>For example <span style="font-family:monospace,&#39; monospace&#39;">ArraySlice&#39;s</span> indices do not: <span style="font-family:monospace,&#39; monospace&#39;">array[2..&lt;5]</span> starts with index 2.<br></div>
<div>Consider the following code to take the 2nd half of the array and remove all empty elements:<br></div>
<div> </div>
<div><span style="font-family:monospace,&#39; monospace&#39;">var array = [ &quot;&quot;, &quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;&quot;, &quot;d&quot; ]</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">var secondHalf = array[array.count/2..&lt;array.count]</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">for (index, element) in secondHalf.enumerate() {</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;"><span style="white-space:pre-wrap"></span>if element == &quot;&quot; {</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;"><span style="white-space:pre-wrap"></span>secondHalf.removeAtIndex(index)</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;"><span style="white-space:pre-wrap"></span>}</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">}</span><br></div>
<div> </div>
<div>This code will crash (ignoring for a moment this should probably be using filter).<br></div>
<div> </div>
<div> </div>
<div> </div>
<div>-- Alternatives<br></div>
<div> </div>
<div>The same effect can already be achieved using the following:<br></div>
<div> </div>
<div><span style="font-family:monospace,&#39; monospace&#39;">for index in collection.indices {</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">  let element = collection[index]</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">  // ...</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">}</span><br></div>
<div> </div>
<div>However having a dedicated <span style="font-family:monospace,&#39; monospace&#39;">(Index, Element)</span> sequence has the following advantages:<br></div>
<div>a) It can help prevent people from using <span style="font-family:monospace,monospace">enumerate()</span> inappropriately.<br></div>
<div>b) It is very common use case that deserves shortening.<br></div>
<div>c) It can be chained (e.g. to map).<br></div>
<div> </div>
<div> </div>
<div> </div>
<div>-- Proposed Solution<br></div>
<div> </div>
<div>Add a property/method on <span style="font-family:monospace,&#39; monospace&#39;">CollectionType</span> that returns a sequence of <span style="font-family:monospace,&#39; monospace&#39;">(Index, Element)</span> tuples.<br></div>
<div>For example, using a property named <span style="font-family:monospace,&#39; monospace&#39;">indexed</span>:<br></div>
<div> </div>
<div><span style="font-family:monospace,&#39; monospace&#39;">for (index, element) in collection.indexed {</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">  // ...</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">}</span><br></div>
<div> </div>
<div>This should be the preferred idiom when you want both the index and the element.<br></div>
<div> </div>
<div>Note that <span style="font-family:monospace,&#39; monospace&#39;">enumerate()</span> does still have valid roles to play:<br></div>
<div>- When you actually do want the element number, not the index.<br></div>
<div>- When you have a <span style="font-family:monospace,&#39; monospace&#39;">SequenceType</span>, as it isn&#39;t indexed.<br></div>
<div> </div>
<div> </div>
<div> </div>
<div>-- Implementation<br></div>
<div> </div>
<div>The feature could be entirely implemented using existing constructs:<br></div>
<div> </div>
<div><span style="font-family:monospace,&#39; monospace&#39;">extension CollectionType {</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">  var indexed: AnySequence&lt;(Index, Generator.Element)&gt; {</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">    return AnySequence(indices.lazy.map { ($0, self[$0]) })</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">  }</span><br></div>
<div><span style="font-family:monospace,&#39; monospace&#39;">}</span><br></div>
<div> </div>
<div>Alternatively, a dedicated <span style="font-family:monospace,&#39; monospace&#39;">SequenceType</span> and/or <span style="font-family:monospace,&#39; monospace&#39;">GeneratorType</span> could be added.<br></div>
<div> </div>
</div>
<div><img style="min-height:1px!important;width:1px!important;border-top-width:0px!important;border-right-width:0px!important;border-bottom-width:0px!important;border-left-width:0px!important;margin-top:0px!important;margin-bottom:0px!important;margin-right:0px!important;margin-left:0px!important;padding-top:0px!important;padding-bottom:0px!important;padding-right:0px!important;padding-left:0px!important" border="0" height="1" width="1" alt="" src="https://www.fastmailusercontent.com/proxy/981667c5fa75d2d6102189c7105ad9f6333023a0ad47163c7ff20e76523c1159/8647470737a3f2f25723030323431303e23647e23756e64676279646e2e65647f27766f2f60756e6f35707e6d3148765176786c673171614a7d2236454230345272776e43694d61464360346d4a727a7d2232443234316973476151574438767a54603e48717739376a58567554664f4a72367a44615c4a49454c6a40354663527463593450736531625351473833695b4377335f43657b473c65366e4f496a4468616935613875637057626d22324872535d2236455d4645414c417e676d43446755785945323468707b695a6a6b6777703b416c6f4a465969363a72463231534f657034707a54663135675144607d22364e673154766843667a63325259395256494036533a4a44394155476d23344d23344/open"><br></div>
<div><u>_______________________________________________</u><br></div>
<div>swift-evolution mailing list<br></div>
<div><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br></div>
<div><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div>
</blockquote><div> </div>

<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=TWMs2ohk0-2BcrwF6GNUK35QNQ48G65bEqXMjRx145i-2BK2pBNfaH-2FaV6xYo7A2ZGuv6y05Zgh5-2B87u-2BAA1jX4EuE0S5zhsyNm-2B-2By-2FD-2FBj1p4R3JXTyyzq8d1XT0hkcyKsYJ1fBV8I3RM6Yd3Z9sgHTmIBjgtoGN34NTzqVxJY7CXtp4k2m-2BK7vwQ5Xw-2B2zkiH7tIMHv-2BFMAW4cFA4k8JiCFFlM568Cs0e5Q2DE-2B6K2bR4-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
</div>


_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div><br>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=fuWmDRE6-2FDdvdUHeLHruUfdigJaxz7nh99l6HfkulY98JVFFd7dDXvhM8NZ5GKsTAjjisC1TVUnjP-2BQItHHN5qI6ZlicxJREKLeA75t322UOxr01KOuncXpRtRRDOJaWYL6fyHR6x2y-2B11yWq5djzKFxJFocNcZs8rTS4IZ5HgknBVBP3T0nHYt6-2BllTvNFSUYBCWe37qpbdxmv7caQdpR9I0One9bReO9vAtfVM-2FGA-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
</div>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">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>
</blockquote></div></div></div>