Mảng mới từ Phạm vi chỉ mục Swift


122

Làm thế nào tôi có thể làm điều gì đó như thế này? Lấy n phần tử đầu tiên từ một mảng:

newNumbers = numbers[0..n]

Hiện đang gặp lỗi sau:

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

BIÊN TẬP:

Đây là chức năng mà tôi đang làm việc.

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

Câu trả lời:


181

Điều này phù hợp với tôi:

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

Vấn đề của bạn có thể là cách bạn khai báo mảng của mình để bắt đầu.

BIÊN TẬP:

Để sửa chữa hàm của bạn, bạn phải truyền Slicevào một mảng:

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]

Tôi đã thêm một chút ngữ cảnh vào câu hỏi của mình, tôi đang làm việc bên trong một hàm. Điều này hoạt động độc lập, nhưng không hoạt động bên trong hàm.
Charlie Egan

1
Đáng yêu! Chúc mừng - điều đó có hiệu quả. Tôi sẽ chấp nhận câu trả lời khi nó cho phép tôi.
Charlie Egan

23
Điểm pedantic, nhưng điều này là không thực sự đúc các Slicemột Array, nhưng thay vì tạo ra một mảng mới từ một lát. Một phép ép kiểu sẽ sử dụng astoán tử: numbers as Arrayđiều này sẽ dẫn đến lỗi.
jb

Ngôn ngữ đã thay đổi, nó sử dụng ba dấu chấm lửng chứ không phải hai developer.apple.com/library/ios/documentation/General/Reference/…
Daniel Galasko

2
Hai dấu chấm được ..đổi thành ..<; ba dấu chấm (dấu chấm lửng) được giữ nguyên. Cảm ơn vì lời nhắc nhở, mặc dù; Tôi đã cập nhật câu trả lời.
Cezary Wojcik

100

# 1. Sử dụngArray chỉ số dưới với phạm vi

Với Swift 5, khi bạn viết…

let newNumbers = numbers[0...position]

newNumbersKhông thuộc loại Array<Int>nhưng thuộc loại ArraySlice<Int>. Đó là bởi vì Arraysubscript(_:​)trả về một ArraySlice<Element>cái mà theo Apple, thể hiện một cái nhìn về bộ nhớ của một số mảng lớn hơn.

Bên cạnh đó, Swift cũng cung cấp Arraymột trình khởi tạo có tên init(_:​)cho phép chúng ta tạo một mảng mới từ sequence(bao gồm ArraySlice).

Do đó, bạn có thể sử dụng subscript(_:​)với init(_:​)để lấy một mảng mới từ n phần tử đầu tiên của một mảng:

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. Sử dụng Array's prefix(_:)phương pháp

Swift cung cấp một prefix(_:)phương thức cho các kiểu tuân theo Collectiongiao thức (bao gồm cả Array). prefix(_:)có khai báo sau:

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

Trả về một dãy con, có độ dài lên đến maxLength, chứa các phần tử ban đầu.

Apple cũng tuyên bố:

Nếu độ dài tối đa vượt quá số phần tử trong tập hợp, kết quả sẽ chứa tất cả các phần tử trong tập hợp.

Do đó, để thay thế cho ví dụ trước, bạn có thể sử dụng mã sau để tạo một mảng mới từ các phần tử đầu tiên của một mảng khác:

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

Vui lòng thêm một số mô tả cho câu trả lời.
Naman

Câu trả lời rất hay. Về cơ bản, nó thực hiện là nó truyền một ArraySlice <T> sang một Array. Cá nhân tôi sẽ không bao gồm nhiều xác nhận. Như tôi thường muốn lát để thất bại nếu tôi cung cấp dãy sai, vv
eonist

0

Thêm một biến thể sử dụng extensionvà tên đối sốrange

Tiện ích mở rộng này sử dụng RangeClosedRange

extension Array {

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


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

Kiểm tra:

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

Cách chức năng mảng:

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

dao động:

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

Ưu điểm của phương pháp này là thực hiện an toàn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.