<div dir="ltr">FWIW: In cases like this, just remember call "<span class="s1">.</span><span class="s2">reverse</span><span class="s1">()</span>" and remove from the back.<div><br></div><div><div>var array = [ "", "a", "b", "c", "", "d" ]</div><div>for (index, element) in array.enumerate().reverse() {</div><div> if element == "" {</div><div> array.removeAtIndex(index)</div><div> }</div><div>}</div><div>print(array) // ["a", "b", "c", "d"]</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 = [ "", "a", "b", "c", "", "d", "", "e", "" , "f", "g", ""]</div><div>var secondHalf = array[array.count/2..<array.count]</div><div>print(secondHalf) // ["", "e", "", "f", "g", ""]</div>
<div>for (index, element) in zip(secondHalf.indices, secondHalf).reverse() {</div><div> if element == "" {</div><div> secondHalf.removeAtIndex(index)</div><div> }</div><div>}</div><div><br></div><div>print(secondHalf) // ["e", "f", "g"]</div><div><br></div><div>Anyway, it would not be correct to ".enumerate()" 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 <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> 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">""</span>, <span style="color:#d12f1b">"a"</span>, <span style="color:#d12f1b">"b"</span>, <span style="color:#d12f1b">"c"</span>, <span style="color:#d12f1b">""</span>, <span style="color:#d12f1b">"d"</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>..<<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">""</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 <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> a écrit :</div><br><div>
<div><div>What you'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's no need to have a dedicated property for it in the stdlib. The few times that I've needed this sort of thing, I'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's pretty simple. But if I ever did need to map it, I'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,' monospace'">(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,' monospace'">(n, Element)</span> tuples,<br></div>
<div>where n is the element *number*, instead of a sequence of <span style="font-family:monospace,' monospace'">(Index, Element)</span>.<br></div>
<div> </div>
<div>1) It doesn't work for collections not indexed by integers.<br></div>
<div> </div>
<div>2) It doesn'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,' monospace'">ArraySlice's</span> indices do not: <span style="font-family:monospace,' monospace'">array[2..<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,' monospace'">var array = [ "", "a", "b", "c", "", "d" ]</span><br></div>
<div><span style="font-family:monospace,' monospace'">var secondHalf = array[array.count/2..<array.count]</span><br></div>
<div><span style="font-family:monospace,' monospace'">for (index, element) in secondHalf.enumerate() {</span><br></div>
<div><span style="font-family:monospace,' monospace'"><span style="white-space:pre-wrap"></span>if element == "" {</span><br></div>
<div><span style="font-family:monospace,' monospace'"><span style="white-space:pre-wrap"></span>secondHalf.removeAtIndex(index)</span><br></div>
<div><span style="font-family:monospace,' monospace'"><span style="white-space:pre-wrap"></span>}</span><br></div>
<div><span style="font-family:monospace,' monospace'">}</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,' monospace'">for index in collection.indices {</span><br></div>
<div><span style="font-family:monospace,' monospace'"> let element = collection[index]</span><br></div>
<div><span style="font-family:monospace,' monospace'"> // ...</span><br></div>
<div><span style="font-family:monospace,' monospace'">}</span><br></div>
<div> </div>
<div>However having a dedicated <span style="font-family:monospace,' monospace'">(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,' monospace'">CollectionType</span> that returns a sequence of <span style="font-family:monospace,' monospace'">(Index, Element)</span> tuples.<br></div>
<div>For example, using a property named <span style="font-family:monospace,' monospace'">indexed</span>:<br></div>
<div> </div>
<div><span style="font-family:monospace,' monospace'">for (index, element) in collection.indexed {</span><br></div>
<div><span style="font-family:monospace,' monospace'"> // ...</span><br></div>
<div><span style="font-family:monospace,' monospace'">}</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,' monospace'">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,' monospace'">SequenceType</span>, as it isn'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,' monospace'">extension CollectionType {</span><br></div>
<div><span style="font-family:monospace,' monospace'"> var indexed: AnySequence<(Index, Generator.Element)> {</span><br></div>
<div><span style="font-family:monospace,' monospace'"> return AnySequence(indices.lazy.map { ($0, self[$0]) })</span><br></div>
<div><span style="font-family:monospace,' monospace'"> }</span><br></div>
<div><span style="font-family:monospace,' monospace'">}</span><br></div>
<div> </div>
<div>Alternatively, a dedicated <span style="font-family:monospace,' monospace'">SequenceType</span> and/or <span style="font-family:monospace,' monospace'">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>