Index Range Swift'den Yeni Dizi


123

Böyle bir şeyi nasıl yapabilirim? Bir diziden ilk n elemanı alın:

newNumbers = numbers[0..n]

Şu anda aşağıdaki hatayı alıyorum:

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

DÜZENLE:

İşte çalıştığım işlev.

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

Yanıtlar:


182

Bu benim için çalışıyor:

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

Sorununuz, dizinizi başlangıçta nasıl ilan ettiğinizle ilgili olabilir.

DÜZENLE:

İşlevinizi düzeltmek için, Slicebir diziye dönüştürmeniz gerekir:

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]

Soruma biraz daha bağlam ekledim, bir fonksiyonun içinde çalışıyorum. Bu bağımsız olarak çalışır, ancak işlevin içinde değildir.
Charlie Egan

1
Güzel! Şerefe - işe yarıyor. Bana izin verdiğinde cevabı kabul edeceğim.
Charlie Egan

23
Bilgiçlik nokta, ama bu gerçekten değil dökümSlice bir etmek Arraydeğil, bir dilim gelen yeni bir dizi oluşturmak. Bir atama asoperatörü kullanır : numbers as Arraybu bir hataya neden olur.
jb


2
İki nokta şu şekilde ..değişti ..<; üç nokta (üç nokta) aynı kalmıştır. Yine de hatırlatma için teşekkürler; Cevabı güncelledim.
Cezary Wojcik

100

# 1. ArrayAralık ile alt simge kullanma

Swift 5 ile yazarken…

let newNumbers = numbers[0...position]

newNumbersTipte değil Array<Int>, tipte ArraySlice<Int>. Bunun nedeni , Apple'a göre Arrays'nin subscript(_:​)bir ArraySlice<Element>o döndürmesidir ve daha büyük bir dizinin depolanmasına ilişkin bir görünüm sunar.

Ayrıca Swift, a'dan (dahil ) yeni bir dizi oluşturmamızı sağlayan Arraybir başlatıcı da sağlar .init(_:​)sequenceArraySlice

Bu nedenle, bir dizinin ilk n öğesinden yeni bir dizi elde etmek için subscript(_:​)with kullanabilirsiniz :init(_:​)

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. Kullanma Arraybireyin prefix(_:)yöntemi

Swift, protokole (dahil ) prefix(_:)uyan türler için bir yöntem sağlar . aşağıdaki beyana sahiptir:CollectionArrayprefix(_:)

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

İlk öğeleri içeren maxLength uzunluğa kadar bir alt dizi döndürür.

Apple ayrıca şunları belirtir:

Maksimum uzunluk, koleksiyondaki öğe sayısını aşarsa, sonuç koleksiyondaki tüm öğeleri içerir.

Bu nedenle, önceki örneğe alternatif olarak, başka bir dizinin ilk öğelerinden yeni bir dizi oluşturmak için aşağıdaki kodu kullanabilirsiniz:

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)])
}

lütfen yanıta biraz açıklama ekleyin.
Naman

Çok güzel cevap. Esasen yaptığı şey, bir ArraySlice <T> 'yi bir Array'e çevirmesidir. Şahsen ben bu kadar çok iddia dahil etmem. Yanlış aralıklar vb.
Sağlarsam

0

extensionVe bağımsız değişken adı kullanan bir varyant daharange

Bu uzantı kullanır RangeveClosedRange

extension Array {

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


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

Testler:

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

Dizi işlevsel yolu:

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

değişmekteydi:

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

Bu yöntemin avantajı, bu tür bir uygulamanın güvenli olmasıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.