索引范围快速的新数组


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
}

Answers:


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]

我在问题中添加了一些上下文,我正在一个函数中工作。这可以独立运行,但不能在函数内部运行。
查理·伊根

1
可爱!干杯-有用。当我接受时,我会接受答案。
查理·伊根

23
迂腐一点,但是这是不是真的铸造Slice一种Array,而是从创造一片新的数组。强制转换将使用as运算符:numbers as Array这将导致错误。
2014年

语言发生了变化,它采用三个省略号而不是两个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>。根据Apple 的说法,这是因为Arraysubscript(_:​)返回了一个ArraySlice<Element>,从而给出了一些较大阵列的存储视图。

此外,Swift还提供了Array一个名为的初始化程序init(_:​),该初始化程序允许我们从sequence(包括ArraySlice)创建一个新数组。

因此,可以使用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协议(包括Array)的类型提供了一种方法。prefix(_:)具有以下声明:

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

请在答案中也添加一些说明。
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 }

这种方法的优点是这样的实现是安全的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.