インデックス範囲スウィフトからの新しい配列


122

どうすればこのようなことができますか?配列から最初のn個の要素を取得します。

newNumbers = numbers[0..n]

現在次のエラーが発生しています:

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

編集:

これが私が働いている関数です。

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

回答:


179

これは私にとってはうまくいきます:

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

あなたの問題は、あなたが最初にあなたの配列をどのように宣言しているかにあるかもしれません。

編集:

関数を修正するSliceには、配列にキャストする必要があります。

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]

質問にもう少しコンテキストを追加しました。関数の内部で作業しています。これは独立して機能しますが、関数内では機能しません。
チャーリーイーガン2014年

1
美しい!乾杯-それはうまくいきます。よろしければお答えします。
チャーリーイーガン2014年

23
知識をひけらかすのポイントが、これは本当にされていないキャストSliceArrayではなく、スライスから新しい配列を作成します。キャストはas演算子を使用します:numbers as Arrayエラーになります。
jb


2
2つのドットがに..変わりました..<。3つのドット(省略記号)は同じままです。ただし、リマインダーをありがとう。答えを更新しました。
Cezary Wojcik、2015年

100

#1。Array範囲付き添え字の使用

Swift 5では、次のように記述します…

let newNumbers = numbers[0...position]

newNumbersはタイプではありませんArray<Int>が、タイプArraySlice<Int>です。Appleによると、Arrays subscript(_:​)はを返すのでArraySlice<Element>、より大きな配列のストレージに対する見方を示しているためです。

さらに、SwiftはArray、(を含む)init(_:​)から新しい配列を作成できるようにすると呼ばれる初期化子も提供します。sequenceArraySlice

したがって、subscript(_:​)with init(_:​)を使用して、配列の最初のn個の要素から新しい配列を取得できます。

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。Arrayprefix(_:)方法を使用する

Swiftは、プロトコル(を含む)にprefix(_:)準拠する型のメソッドを提供しCollectionますArrayprefix(_:)次の宣言があります:

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

初期要素を含む、最大長がmaxLengthのサブシーケンスを返します。

アップルも述べています:

最大長がコレクション内の要素数を超える場合、結果にはコレクション内のすべての要素が含まれます。

したがって、前の例の代わりに、次のコードを使用して、別の配列の最初の要素から新しい配列を作成できます。

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

回答にも説明を追加してください。
ナマン2016年

とてもいい答えです。基本的には、ArraySlice <T>を配列にキャストします。個人的には、アサートをあまり含めません。私は通常、誤った範囲などを指定した場合にスライスが失敗するようにしたい
eonist

0

extension引数名を使用するもう1つのバリアントrange

この拡張機能はRangeClosedRange

extension Array {

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


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

テスト:

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

配列の機能的な方法:

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

範囲:

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

この方法の利点は、そのような実装が安全であることです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.