Ci sono vari modi fantastici per farlo con il filtro, ma la maggior parte richiederebbe probabilmente due passaggi piuttosto che uno, quindi potresti anche usare un ciclo for.
Prenotare lo spazio in anticipo potrebbe fare una grande differenza in questo caso, poiché se la sorgente è grande eviterà una ridistribuzione non necessaria man mano che i nuovi array cresceranno e il calcolo dello spazio necessario è in tempo costante sugli array.
// could make this take a more generic random-access collection source
// if needed, or just make it an array extension instead
func splitAlternating<T>(source: [T]) -> ([T],[T]) {
var evens: [T] = [], odds: [T] = []
evens.reserveCapacity(source.count/2 + 1)
odds.reserveCapacity(source.count/2)
for idx in indices(source) {
if idx % 2 == 0 {
evens.append(source[idx])
}
else {
odds.append(source[idx])
}
}
return (evens,odds)
}
let a = [0,1,2,3,4,5,6]
splitAlternating(a) // ([0, 2, 4, 6], [1, 3, 5])
Se le prestazioni sono veramente critica, è possibile utilizzare source.withUnsafeBufferPointer
per accedere agli elementi di origine, per evitare i limiti Indice CONTROLLO.
Se gli array sono davvero enormi, e non si ha intenzione di utilizzare i dati risultanti, tranne per assaggiare un piccolo numero di elementi, si potrebbe considerare l'utilizzo di una vista pigro invece (anche se lo std LIB pigro isn filtro' t molto utile qui in quanto restituisce la sequenza non una raccolta - potrebbe essere necessario scrivere il proprio).
fonte
2015-03-15 02:59:32
Il meglio che si vuole ottenere è 'O (n) '. Basta creare due nuovi array e scorrere il vecchio, alternando dove si mette un elemento su ogni iterazione. – royhowie