2015-04-22 15 views
5

C'è un modo in cui posso chiamare la funzione di riduzione su una serie di tuple per trovare un valore massimo?Rapido Ridurre una serie di tuple in

Per esempio

struct Gate{ 

    var maxedOpenGates = 1 

    var GatesOpen : [(openOrdered : Int, gateNum : Int)] = [] 

    init(defaultSelected : Int = 0){ 

     GatesOpen.append(openOrdered : 1, gateNum : defaultSelected) 
    } 

    private func manipulateGates(gates : [SegmentButton]){ 
     for i in GatesOpen{ 
      gates[i.gateNum].toggleSelected() 
     } 

    } 

    mutating func openGate(index : Int, buttons : [SegmentButton]){ 

     if GatesOpen.count < maxedOpenGates{ 
      GatesOpen.append( openOrdered: GatesOpen.count , gateNum: index) 

     }else{ 
     //////Finding the gate that was Opened the longest//// 
      let lastGate = GatesOpen.reduce(Int.min,{ max($0,$1) }) 

     } 
     manipulateGates(buttons) 
    } 
} 

in cui una che sto cercando di ridurre basano su openOrdered

let lastGate = GatesOpen.reduce(Int.min,{ max($0,$1) }) 

risposta

4

Sì, è possibile ridurre una serie di tuple come qualsiasi altro array. Gli argomenti della funzione combinata sono elementi dell'array, nel tuo caso "gate tuples" . E se il risultato di ridurre la matrice dovrebbe essere una tupla porta poi l'elemento iniziale e il risultato della funzione combinare deve essere anche di quel tipo:

let lastGate = gatesOpen.reduce(gatesOpen[0]) { 
     $0.openOrdered < $1.openOrdered ? $1 : $0 
} 

Naturalmente la matrice deve avere almeno un elemento per questo funziona. Per evitare il confronto non necessario di gatesOpen[0] con se stesso si può cambiare a (modificato dopo @ commento di Airspeed):

let lastGate = dropFirst(gatesOpen).reduce(gatesOpen[0]) { 
    $0.openOrdered < $1.openOrdered ? $1 : $0 
} 
+1

Trovo 'dropFirst (gatesOpen)' è un po 'più bello dell'operazione di slicing manuale. Se vuoi rendere conto della possibilità dell'array vuoto con un optional, puoi usare 'first.map' per restituire un' nil' se l'array è vuoto: 'let lastGate = gatesOpen.first.map {fst in dropFirst (gatesOpen) .reduce (fst) { $ 0.openOrdered <$ 1.openOrdered? $ 1: $ 0 } } ' –

+0

@AirspeedVelocity: buona idea con dropFirst. - Avevo anche pensato di gestire un array vuoto (il tuo suggerimento è molto elegante!), Ma dal codice dato mi è sembrato che ci fosse almeno un "gate", quindi non volevo complicare le cose. Grazie per il feedback. –

+0

Molto bello! La spiegazione sopra, integrata con gli esempi, aiuta molto la mia comprensione della funzione di riduzione e di altre funzioni che imitano tale design. – MooCow

3

Utilizzando chiusura con ridurre la funzione,

//////Finding the gate that was Opened the longest//// 
let intitalValue = (Int.min,Int.min) 
let lastGate: (openOrdered: Int, gateNum: Int) = GatesOpen.reduce(intitalValue){ 
     (longestOpenGate: (openOrdered: Int, gateNum: Int), gate) in 
      if(longestOpenGate.openOrdered < gate.openOrdered) { 
        return gate; 
      } else { 
        return longestOpenGate; 
      } 

} 
let lastGateNumber = lastGate.gateNum; 

Oppure,

let lastGate: (openOrdered: Int, gateNum: Int) = GatesOpen.reduce(intitalValue){ 
    $0.openOrdered < $1.openOrdered ? $1 : $0 
} 
let lastGateNumber = lastGate.gateNum; 
Problemi correlati