2015-12-31 12 views

risposta

12

È possibile utilizzare un ciclo progressione chiamato passo (a :, da :) a iterare gli elementi ogni n elementi:

Xcode 8.3.2 • Swift 3,1

let array = Array(1...5) 

let pairs = stride(from: 0, to: array.count, by: 2).map { 
    (array[$0], $0 < array.count-1 ? array[$0.advanced(by: 1)] : nil) 
} // [(.0 1, {some 2}), (.0 3, {some 4}), (.0 5, nil)] 

print(pairs) // "[(1, Optional(2)), (3, Optional(4)), (5, nil)]\n" 
+1

Nota: il primo elemento della tupla non ha bisogno di essere un opzionale considerando il fatto che l'array di input ha solo interi (Int) e quindi non sarà mai nullo quindi puoi dichiararlo come [(Int, Int?) ] –

+1

Fantastico! Che ne dici di qualcosa che non è indicizzabile da intero? – fumoboy007

+0

@ fumoboy007 Non sapevo che si potesse avere un array non indicizzabile dal numero intero –

1

Se l'array avrà un numero di elementi, si sarebbe in grado di scrivere qualcosa del genere:

for i in 0...arr.count/2 { 
    print(arr[2*...2*i+1]) 

Tuttavia questo non è sempre il caso. Inoltre, nil non è sempre compatibile con il tipo di elementi nella matrice, come quello nell'esempio (nil non è compatibile con Int, solo con Int?).

Un'altra soluzione potrebbe essere quella di estendere Array e aggiungere un metodo pair(), che restituisce una tupla (le tuple possono essere eterogenee). Puoi usare pair per camminare all'interno di tutte le coppie dell'array, oppure puoi estendere ancora di più la struttura Array e aggiungere pairs() che restituisce una serie di tuple. Nota che dal momento che il secondo elemento della tupla è uno Optional, dovrai scartarlo prima dell'uso.

extension Array { 
    func pair(i: Index) -> (Element, Element?) { 
     return (self[i], i < self.count - 1 ? self[i+1] : nil) 
    } 

    func pairs() -> [(Element, Element?)] { 
     var result = [(Element, Element?)]() 
     for i in 0...arr.count/2 { 
      result.append(self.pair(2*i)) 
     } 
     return result 
    } 
} 

let arr = [1, 2, 3, 4, 5] 

for i in 0...arr.count/2 { 
    print(arr.pair(2*i)) 
} 

for pair in arr.pairs() { 
    print(pair) 
} 
0

Un approccio sarebbe incapsulare l'array in una classe. I valori di ritorno per ottenere coppie di articoli sarebbero opzionali per la protezione da chiamate fuori intervallo.

Esempio:

class Pairs { 

    let source = [1, 2, 3, 4, 5] // Or set with init() 
    var offset = 0 

    func nextpair() -> (Int?, Int?) { 
     var first: Int? = nil 
     var second: Int? = nil 
     if offset < source.count { 
      first = source[offset] 
      offset++ 
     } 
     if offset < source.count { 
      second = source[offset] 
      offset++ 
     } 
     return (first, second) 
    } 

} 
1

io personalmente non piace scorrendo la metà della lista (soprattutto a causa del dividendo), ecco come mi piace farlo:

let array = [1,2,3,4,5]; 
var i = 0; 

while i < array.count { 
    var a = array[i]; 
    var b : Int? = nil; 
    if i + 1 < array.count { 
     b = array[i+1]; 
    } 
    print("(\(a), \(b))"); 

    i += 2; 
} 

È scorrere l'array incrementando di 2.

Se si desidera avere nulla nell'elemento, è necessario utilizzare optionals.

+0

Si dovrebbe' Si dichiara a let, in quanto il suo valore non cambia. – Cristik