Swift Array instance method drop(at: Int)

可紊 提交于 2019-12-13 03:47:49

问题


Array in Swift has several instance methods for excluding elements, such as dropFirst(), dropLast(), drop(while:), etc. What about drop(at:)?

Note: I'd use remove(at:), but the array I'm working with is a let constant.


回答1:


Note: I'd use remove(at:), but the array I'm working with is a constant.

I wouldn't let that stop you:

extension Array {
    func drop(at:Int) -> [Element] {
        var temp = self
        temp.remove(at: at)
        return temp
    }
}
let numbers = [1, 2, 3, 4, 5]
print(numbers.drop(at: 2)) // [1, 2, 4, 5]



回答2:


You can extend RangeReplaceableCollection protocol instead of Array type, this way you can use it on Strings as well:

extension RangeReplaceableCollection {
    func drop(at offset: Int) -> SubSequence {
        let index = self.index(startIndex, offsetBy: offset, limitedBy: endIndex) ?? endIndex
        let next = self.index(index, offsetBy: 1, limitedBy: endIndex) ?? endIndex
        return self[..<index] + self[next...]
    }
}

var str = "Hello, playground"
str.drop(at: 5)  // "Hello playground"

let numbers = [1, 2, 3, 4, 5]
print(numbers.drop(at: 2))  // "[1, 2, 4, 5]\n"

If you would like to accept also String.Index in your method:

extension RangeReplaceableCollection {
    func drop(at index: Index) -> SubSequence {
        let index = self.index(startIndex, offsetBy: distance(from: startIndex, to: index), limitedBy: endIndex) ?? endIndex
        let next = self.index(index, offsetBy: 1, limitedBy: endIndex) ?? endIndex
        return self[..<index] + self[next...]
    }
}

var str = "Hello, playground"
str.drop(at: 0)               // "ello, playground"
str.drop(at: str.startIndex)  // "ello, playground"



回答3:


The only thing I would add to your implementation is a guard statement with a useful error message:

extension Array {
    func drop(at index: Int) -> ArraySlice<Element> {
        guard indices.contains(index) else {
            fatalError("Index out of range")
        }
        return self[0..<index] + self[(index+1)..<endIndex]
    }

    func drop(range: CountableRange<Int>) -> ArraySlice<Element> {
        guard (indices.lowerBound, range.upperBound) <= (range.lowerBound, indices.upperBound) else {
            fatalError("Range is out of the indices bounds")
        }
        return self[0..<range.lowerBound] + self[range.upperBound..<endIndex]
    }
}

let a = [1,2,3]
a.drop(at: 3)          //Fatal error: Index out of range
let b = [0,1,2,3,4,5]
b.drop(range: 1..<5)   //[0, 5]



回答4:


return self[0..<index] + self[index+1..<endIndex]

Ugly. Why not use the tools you're given?

extension Array {
    func drop(at:Int) -> ArraySlice<Element> {
        return prefix(upTo: at) + suffix(from: at+1)
    }
}
let arr = [1,2,3,4,5]
let slice = arr.drop(at:2) // [1,2,4,5]

EDIT It seems Apple would prefer you to say (using partial ranges)

return self[..<at] + self[(at+1)...]

but personally I think that's uglier, and after all the methods I suggested are not deprecated or anything.




回答5:


How about using a Swift extension to add drop(at:) to the Array structure?

extension Array {
  func drop(at index: Int) -> ArraySlice<Element> {
    precondition(indices.contains(index), "Index out of range")
    return self[..<index] + self[(index+1)...]
  }
}

It returns a slice of the original array without the element at the specified index.

let numbers = [1, 2, 3, 4, 5]
print(numbers.drop(at: 2))
// Prints "[1, 2, 4, 5]"

Note: You may also want to add drop(at:) to ArraySlice.



来源:https://stackoverflow.com/questions/52350697/swift-array-instance-method-dropat-int

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!