Nuovo array da Index Range Swift


122

Come posso fare qualcosa di simile? Prendi i primi n elementi da un array:

newNumbers = numbers[0..n]

Attualmente ricevendo il seguente errore:

error: could not find an overload for 'subscript' that accepts the supplied arguments

MODIFICARE:

Ecco la funzione in cui sto lavorando.

func aFunction(numbers: Array<Int>, position: Int) -> Array<Int> {
    var newNumbers = numbers[0...position]
    return newNumbers
}

Risposte:


181

Questo funziona per me:

var test = [1, 2, 3]
var n = 2
var test2 = test[0..<n]

Il tuo problema potrebbe essere il modo in cui dichiari il tuo array per cominciare.

MODIFICARE:

Per correggere la tua funzione, devi eseguire il cast Slicesu un array:

func aFunction(numbers: Array<Int>, position: Int) -> Array<Int> {
    var newNumbers = Array(numbers[0..<position])
    return newNumbers
}

// test
aFunction([1, 2, 3], 2) // returns [1, 2]

Ho aggiunto un po 'più di contesto alla mia domanda, sto lavorando all'interno di una funzione. Funziona indipendentemente, ma non all'interno della funzione.
Charlie Egan

1
Bello! Salute, funziona. Accetterò la risposta quando me lo permetterà.
Charlie Egan

23
Punto pedante, ma questo non è realmente gettando il Slicead una Array, ma creando un nuovo sistema da una fetta. Un cast userebbe l' asoperatore: numbers as Arrayche risulterebbe in un errore.
jb

La lingua è cambiata, utilizza tre puntini di sospensione e non due developer.apple.com/library/ios/documentation/General/Reference/…
Daniel Galasko

2
I due punti sono ..cambiati in ..<; i tre punti (un'ellissi) sono rimasti gli stessi. Grazie per il promemoria, però; Ho aggiornato la risposta.
Cezary Wojcik

100

# 1. Utilizzo di Arraypedice con intervallo

Con Swift 5, quando scrivi ...

let newNumbers = numbers[0...position]

... newNumbersnon è di tipo Array<Int>ma è di tipo ArraySlice<Int>. Questo perché Arrayèsubscript(_:​) restituisceArraySlice<Element> , secondo Apple, presenta una vista sull'archiviazione di un array più grande.

Inoltre, Swift fornisce anche Arrayun inizializzatore chiamato init(_:​)che ci consente di creare un nuovo array da un sequence(inclusoArraySlice ).

Pertanto, puoi usare subscript(_:​)coninit(_:​) per ottenere un nuovo array dai primi n elementi di un array:

let array = Array(10...14) // [10, 11, 12, 13, 14]
let arraySlice = array[0..<3] // using Range
//let arraySlice = array[0...2] // using ClosedRange also works
//let arraySlice = array[..<3] // using PartialRangeUpTo also works
//let arraySlice = array[...2] // using PartialRangeThrough also works
let newArray = Array(arraySlice)
print(newArray) // prints [10, 11, 12]

# 2. Utilizzando Array'sprefix(_:) metodo di

Swift fornisce un prefix(_:)metodo per i tipi conformi al Collectionprotocollo (inclusiArray ). prefix(_:)ha la seguente dichiarazione:

func prefix(_ maxLength: Int) -> ArraySlice<Element>

Restituisce una sottosequenza, fino a maxLength di lunghezza, contenente gli elementi iniziali.

Apple afferma inoltre:

Se la lunghezza massima supera il numero di elementi nella raccolta, il risultato contiene tutti gli elementi nella raccolta.

Pertanto, in alternativa all'esempio precedente, è possibile utilizzare il codice seguente per creare un nuovo array dai primi elementi di un altro array:

let array = Array(10...14) // [10, 11, 12, 13, 14]
let arraySlice = array.prefix(3)
let newArray = Array(arraySlice)
print(newArray) // prints [10, 11, 12]

7
func subArray<T>(array: [T], range: NSRange) -> [T] {
  if range.location > array.count {
    return []
  }
  return Array(array[range.location..<min(range.length, array.count)])
}

per favore aggiungi anche una descrizione alla risposta.
Naman

Risposta molto bella. Quello che fa essenzialmente è che esegue il cast di un ArraySlice <T> a un Array. Personalmente non includerei tante affermazioni. Poiché di solito voglio che lo slice fallisca se fornisco intervalli falsi, ecc.
eonista

0

Un'altra variante che usa extensione il nome dell'argomentorange

Questa estensione utilizza RangeeClosedRange

extension Array {

    subscript (range r: Range<Int>) -> Array {
        return Array(self[r])
    }


    subscript (range r: ClosedRange<Int>) -> Array {
        return Array(self[r])
    }
}

test:

func testArraySubscriptRange() {
    //given
    let arr = ["1", "2", "3"]

    //when
    let result = arr[range: 1..<arr.count] as Array

    //then
    XCTAssertEqual(["2", "3"], result)
}

func testArraySubscriptClosedRange() {
    //given
    let arr = ["1", "2", "3"]

    //when
    let result = arr[range: 1...arr.count - 1] as Array

    //then
    XCTAssertEqual(["2", "3"], result)
}

0

Modo funzionale della matrice:

   array.enumerated().filter { $0.offset < limit }.map { $0.element }

a distanza:

 array.enumerated().filter { $0.offset >= minLimit && $0.offset < maxLimit }.map { $0.element }

Il vantaggio di questo metodo è che tale implementazione è sicura.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.