Swift에서 슬라이스는 무엇입니까?


85

Swift의 슬라이스는 무엇이며 배열과 어떻게 다릅니 까?

문서에서 subscript (Range)의 유형 서명은 다음과 같습니다.

subscript(Range<Int>) -> Slice<T>

Array<T>대신 다른 것을 반환하지 Slice<T>않습니까?

슬라이스를 배열과 연결할 수있는 것 같습니다.

var list = ["hello", "world"]
var slice: Array<String> = [] + list[0..list.count]

그러나 이것은 오류를 생성합니다.

제공된 인수를 허용하는 'subscript'에 대한 오버로드를 찾을 수 없습니다.

var list = ["hello", "world"]
var slice: Array<String> = list[0..list.count]

슬라이스 란?

답변:


97

슬라이스가 배열을 가리 킵니다. 배열이 이미 존재하고 슬라이스가 원하는 부분을 설명 할 수있는 경우 다른 배열을 만드는 점이 없습니다.

추가는 암시 적 강제를 유발하므로 작동합니다. 과제 작동하려면, 당신은 강제해야합니다 :

var list = ["hello", "world"]
var slice: Array<String> = Array(list[0..<list.count])

말이 되네요. 문서의 어디에나 설명되어 있습니까?
hjing

2
실제로 구현 세부 사항입니다. 블랙 박스의 동작을 드러내는 엣지 케이스를 영리하게 조사 해봤는데 ...!
matt

2
실제로 Slice는 배열의 복사본입니다. 원래 배열을 업데이트하면 슬라이스가 변경되지 않습니다. 이것은 구조체 특성 때문입니다. 참고로 Sliceable 프로토콜은 Slice 유형의 사용을 의미하지 않습니다
Marcin

4
스위프트 언어는 변경 및 조각은 실제로 세 가지 줄임표를 사용하지이있다 developer.apple.com/library/ios/documentation/General/Reference/...
다니엘 Galasko

7
범위 연산자가 변경되었음을 새로운 독자에게 알리는 간단한 편집을 추가하면 서신이 깨지지 않습니까?
Daniel Galasko 2015 년

22

참고 : 배열이 이제 진정한 값 유형이기 때문에이 답변은 Swift 베타 3에서 유효하지 않습니다.


@matt가 정확합니다. 위의- Slice<T>배열에 대한 포인트. 이는 Swift가 작업중인 다른 모든 데이터 유형을 처리하는 방식과 반대되는 것 같습니다. 이는 슬라이스가 상수로 선언 된 경우에도 값이 변경 될 수 있음을 의미하기 때문입니다.

var arr = ["hello", "world", "goodbye"]    // ["hello", "world", "goodbye"]
let slice = arr[0..2]                      // ["hello", "world"]
arr[0] = "bonjour"
println(slice)                             // ["bonjour", "world"]

최악의 부분은 슬라이스가 배열처럼 작동한다는 것입니다. Swift에서 우리는 불변성에 대한 기대를 가지고 있다는 점을 감안할 때 슬라이스의 첨자 값이 경고없이 변경 될 수 있다는 것은 위험 해 보입니다.

println(slice[1])                          // "world"
arr[1] = "le monde"
println(slice[1])                          // "le monde"

그러나 기본 배열이 너무 급격하게 변경되면 연결이 해제됩니다.

arr.removeAtIndex(0)                       // this detaches slice from arr
println(slice)                             // ["bonjour", "le monde"]
arr[0] = "hola"
println(slice)                             // ["bonjour", "le monde"]

6
사실, 조각 작품 단지 당신이 말한대로, 배열과 같은. Swift 배열은 immutable로 선언 된 경우에도 변경 가능한 요소를 가지고 있습니다 . 예를 들어 let arr = ["hello", "world", "goodbye"]; arr[0] = "bonjour". 당신은 그것이 작동한다는 것을 알게 될 것입니다. 변경 불가능한 배열의 경우 이상하게도 내용이 아닌 변경 불가능한 크기 입니다. (에서 페이지의 "컬렉션의 가변성" 스위프트 프로그래밍 언어 )
매트 깁슨

1
"변경 가능한 요소"- 이것은 더 이상 사실입니다
알렉스 브라운

14

요약:

위의 답변은 베타 3까지 사실입니다 (향후 릴리스에서 다시 변경 될 수 있음).

Slice는 이제 배열처럼 작동하지만 @matt가 위에서 말했듯이 변경이 이루어질 때까지 사실상 내부 배열에 대한 얕은 복사본입니다. 슬라이스 (현재)는 원래 값의 스냅 샷을보고,

또한 슬라이스 구문이 변경되었습니다.

[from..upToButNotIncluding] -> [from..<upToButNotIncluding]

예:

var arr = ["hello", "world", "goodbye"] // ["hello", "world", "goodbye"]
var arrCopy = arr
let slice = arr[0..<2]                  // ["hello", "world"]
arr[0] = "bonjour"
arr                                     // ["bonjour", "world", "goodbye"]
arrCopy                                 // ["hello", "world", "goodbye"]
slice                                   // ["hello", "world"]

이것은 파이썬 스타일 목록 처리를 수행하는 것이 더 간단하기 때문에 (IMHO) 훨씬 더 균일 한 처리를 허용합니다. 하나의 목록을 필터링하여 다른 목록을 만듭니다. Beta 3 이전의 Matt의 답변에 따라 슬라이스를 매핑하려면 임시 배열을 만들어야했습니다. 이제 새 코드가 더 간단 해졌습니다.

class NameNumber {
    var name:String = ""
    var number:Int = 0

    init (name:String, number:Int) {
        self.name = name
        self.number = number
    }
}

var number = 1
let names = ["Alan", "Bob", "Cory", "David"]
let foo = names[0..<2].map { n in NameNumber(name:n, number:number++) }
foo     // [{name "Alan" number 1}, {name "Bob" number 2}]

(공평하기는하지만, foo는 여전히 슬라이스입니다)

참고:

http://adcdownload.apple.com//Developer_Tools/xcode_6_beta_3_lpw27r/xcode_6_beta_3_release_notes__.pdf

중요한 변경 사항, 해결 된 문제,-Swift Language, 단락 1

"Swift의 배열은 Dictionary 및 String ... m과 같은 완전한 값 의미를 갖도록 완전히 재 설계되었습니다."

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.