2015-09-21 28 views
6

Bir diziyi numaralandırmak istiyorsanız (bir öğenin dizinini değeriyle birlikte kullanmam gereken bir map() işlevi için), enumerate() işlevini kullanabilirim. Ör: (Ben diziden bazı alt dizisini kullanmak istiyorsanız ŞimdiOrijinal dilimleri kullanarak bir dilim nasıl numaralandırılır?

import Foundation 

let array: [Double] = [1, 2, 3, 4] 

let powersArray = array.enumerate().map() { 
    pow($0.element, Double($0.index)) 
} 

print("array == \(array)") 
print("powersArray == \(powersArray)") 

// array == [1.0, 2.0, 3.0, 4.0] 
// powersArray == [1.0, 2.0, 9.0, 64.0] <- As expected 

, ben bir slice kullanabilir ve ben orijinal dizide kullanmak gibi beni sadece aynı endeks kullanmasına izin vereceğini Bu, for döngüsünde subscript erişimcisini kullanacak olursam istediğim şeydir. Örn .:

let range = 1..<(array.count - 1) 
let slice = array[range] 
var powersSlice = [Double]() 

for index in slice.indices { 
    powersSlice.append(pow(slice[index], Double(index))) 
} 

print("powersSlice == \(powersSlice)") 

// powersSlice == [2.0, 9.0] <- As expected 

Ancak, ben o zaman ben tamamen farklı bir davranış olsun, ben orijinal dizideki yaptığı gibi enumerate().map() yaklaşım kullanmaya çalışmalısınız. Bunun yerine endeksleri slice 'ın aralığının Yeni, 0 tabanlı dizi alacağı:

let powersSliceEnumerate = slice.enumerate().map() { 
    pow($0.element, Double($0.index)) 
} 

print("powersSliceEnumerate == \(powersSliceEnumerate)") 

// powersSliceEnumerate == [1.0, 3.0] <- Not as expected 

Soru iyi yol olup olmadığını (yani farklarını veya bir şey kullanarak manuel ayarlar olmadan) kullanılarak bir dilim numaralandırmak için kendi endeksleri ve otomatik olarak oluşturulmuş 0 tabanlı olanlar değil?

+1

Değil sorunuzun cevabı, ancak 'let powersSlice = dilim için-döngü yerini alabilir .indices.map {pow (dilim [$ 0], Çift (0 $))} ' –

+0

Teşekkürler, @MartinR. Önerinizi, 'sayım' tarafından oluşturulan endeks aralığını dengelemekten daha iyi bir çözüm olarak akılda tutacağım. – courteouselk

cevap

4

enumerate()n s sıfırda başlayan ardışık Int ler vardır (n, elem) çifti, bir dizi döner. Bu, SequenceType için bir protokol uzantısı yöntemi olduğundan ve isteğe bağlı bir sıra öğelerin mutlaka öğelerle ilişkili dizine sahip olmadığından mantıklıdır.

let powersSlice = slice.indices.map { pow(slice[$0], Double($0)) } 

veya

let powersSlice = zip(slice.indices, slice).map { pow($1, Double($0)) } 

İkinci yaklaşım keyfi koleksiyonları için bir protokol uzantısı yönteme jeneralize olabilir ile Eğer beklenen sonucu elde edersiniz:

extension CollectionType { 
    func indexEnumerate() -> AnySequence<(index: Index, element: Generator.Element)> { 
     return AnySequence(zip(indices, self)) 
    } 
} 

Bu (index, elem) çiftleri bir dizi döndürür Burada index , koleksiyonun bir indeksi ve ilgili elemanın elem dizisidir. AnySequence, arayandan zip() döndürülen belirli türdeki Zip2Sequence<RangeGenerator<Self.Index>, Self> "gizlemek" için kullanılır.

Örnek: Swift 3

let powersSliceEnumerate = slice.indexEnumerate().map() { pow($0.element, Double($0.index)) } 
print("powersSliceEnumerate == \(powersSliceEnumerate)") 
// powersSliceEnumerate == [2.0, 9.0] 

Güncelleme:

extension Collection { 
    func indexEnumerate() -> AnySequence<(Indices.Iterator.Element, Iterator.Element)> { 
     return AnySequence(zip(indices, self)) 
    } 
} 
+0

Mükemmel. Teşekkür ederim. – courteouselk