Index Range Swift의 새로운 배열


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]

내 질문에 컨텍스트를 조금 더 추가했으며 함수 내부에서 작업하고 있습니다. 이것은 독립적으로 작동하지만 함수 내부에서는 작동하지 않습니다.
Charlie Egan

1
아름다운! 건배-작동합니다. 나는 그것이 나를 허락 할 때 대답을 받아 들일 것이다.
Charlie Egan

23
현학적 인 점은, 그러나 이것은 정말되지 캐스팅SliceArray, 오히려 조각의 새로운 배열을 생성. 캐스트는 as연산자를 사용하므로 numbers as Array오류가 발생합니다.
JB

언어는 세 가지 줄임표를 사용하지이 변경되었습니다 developer.apple.com/library/ios/documentation/General/Reference/...
다니엘 Galasko

2
두 점이로 ..변경되었습니다 ..<. 세 개의 점 (줄임표)은 동일하게 유지됩니다. 그래도 상기시켜 주셔서 감사합니다. 답변을 업데이트했습니다.
Cezary Wojcik

100

#1. Array범위와 함께 아래 첨자 사용

Swift 5로 쓸 때…

let newNumbers = numbers[0...position]

newNumbers유형은 Array<Int>아니지만 유형 ArraySlice<Int>입니다. 그 때문에 Array의 ' 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(_:)을 준수하는 유형에 대한 메소드를 제공합니다 . 다음과 같은 선언이 있습니다.CollectionArrayprefix(_:)

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

초기 요소를 포함하는 최대 maxLength 길이의 하위 시퀀스를 반환합니다.

Apple은 또한 다음과 같이 말합니다.

최대 길이가 컬렉션의 요소 수를 초과하면 결과에 컬렉션의 모든 요소가 포함됩니다.

따라서 이전 예제의 대안으로 다음 코드를 사용하여 다른 배열의 첫 번째 요소에서 새 배열을 만들 수 있습니다.

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

답변에 대한 설명도 추가하십시오.
Naman

아주 좋은 대답입니다. 본질적으로하는 일은 ArraySlice <T>를 Array로 캐스팅하는 것입니다. 개인적으로 나는 많은 주장을 포함하지 않을 것입니다. 일반적으로 잘못된 범위 등을 제공하면 슬라이스가 실패하기를 원합니다.
eonist

0

extension및 인수 이름을 사용하는 또 다른 변형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.