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 <mailto:swift-evolution@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-evolution >> <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