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.