FWIW: In cases like this, just remember call ".reverse()" and remove from the back.
var array = [ "", "a", "b", "c", "", "d" ] for (index, element) in array.enumerate().reverse() { if element == "" { array.removeAtIndex(index) } } print(array) // ["a", "b", "c", "d"] zip is useful when we have ArraySlice as has been said before: var array = [ "", "a", "b", "c", "", "d", "", "e", "" , "f", "g", ""] var secondHalf = array[array.count/2..<array.count] print(secondHalf) // ["", "e", "", "f", "g", ""] for (index, element) in zip(secondHalf.indices, secondHalf).reverse() { if element == "" { secondHalf.removeAtIndex(index) } } print(secondHalf) // ["e", "f", "g"] Anyway, it would not be correct to ".enumerate()" returns (Index, Element) instead of (n, Element)? I believe that the current behavior was thought when Slices had indices starting with zero. Em ter, 29 de dez de 2015 às 00:30, Dany St-Amant via swift-evolution < swift-evolution@swift.org> escreveu: > > 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: > > var array = [ "", "a", "b", "c", "", "d" ] > var secondHalf = array[array.count/2..<array.count] > for (index, element) in zip(secondHalf.indices, secondHalf) { > if element == "" { > secondHalf.removeAtIndex(index) > } > } > > 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. > > Dany St-Amant > > > Le 28 déc. 2015 à 01:06, Kevin Ballard via swift-evolution < > swift-evolution@swift.org> a écrit : > > 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 > > for index in col.indices { > let elt = col[index] > // ... > } > > and that's pretty simple. But if I ever did need to map it, I'd just use > the aforementioned zip() expression. > > -Kevin Ballard > > On Sun, Dec 27, 2015, at 12:08 AM, Patrick Pijnappel via swift-evolution > wrote: > > -- Introduction > > There should be a property on CollectionType that returns a sequence of > (Index, Element) tuples. > Currently enumerate() is often used instead, but it is not well suited to > the task and can lead to bugs. > > > > -- Motivation > > Using enumerate() instead of an (Index, Element) sequence has two main > problems. > Both arise because enumerate() returns a sequence of (n, Element) tuples, > where n is the element *number*, instead of a sequence of (Index, Element) > . > > 1) It doesn't work for collections not indexed by integers. > > 2) It doesn't do what you might expect in some cases, as indices do not > always start at 0. > For example ArraySlice's indices do not: array[2..<5] starts with index 2. > Consider the following code to take the 2nd half of the array and remove > all empty elements: > > var array = [ "", "a", "b", "c", "", "d" ] > var secondHalf = array[array.count/2..<array.count] > for (index, element) in secondHalf.enumerate() { > if element == "" { > secondHalf.removeAtIndex(index) > } > } > > This code will crash (ignoring for a moment this should probably be using > filter). > > > > -- Alternatives > > The same effect can already be achieved using the following: > > for index in collection.indices { > let element = collection[index] > // ... > } > > However having a dedicated (Index, Element) sequence has the following > advantages: > a) It can help prevent people from using enumerate() inappropriately. > b) It is very common use case that deserves shortening. > c) It can be chained (e.g. to map). > > > > -- Proposed Solution > > Add a property/method on CollectionType that returns a sequence of (Index, > Element) tuples. > For example, using a property named indexed: > > for (index, element) in collection.indexed { > // ... > } > > This should be the preferred idiom when you want both the index and the > element. > > Note that enumerate() does still have valid roles to play: > - When you actually do want the element number, not the index. > - When you have a SequenceType, as it isn't indexed. > > > > -- Implementation > > The feature could be entirely implemented using existing constructs: > > extension CollectionType { > var indexed: AnySequence<(Index, Generator.Element)> { > return AnySequence(indices.lazy.map { ($0, self[$0]) }) > } > } > > Alternatively, a dedicated SequenceType and/or GeneratorType could be > added. > > > *_______________________________________________* > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution