有没有办法在swift中限制数组大小,以便在它满了时附加元素,它不会附加?
我知道这可以通过编程方式完成。想知道swift是否有内置处理。
例如:
数组 - >大小为10的数组
array.append(1)
.
.
.
array.append(10)
array.append(11) // Doesn't do anything?
array.insert(0, pos: 0)
用例:将最后一个元素推出数组以为新元素腾出空间?
编辑 - 最后一行是主要用例。
答案 0 :(得分:1)
不,Swift没有附带这种数组 - 类似于数据库中的View - 允许你查看前N个元素。虽然为此,视图和目标都应该是引用类型,但在Swift for arrays中不是这种情况。
但是,如果有足够的诽谤,你可以快速在Array
上写一个包装来满足你的需求:
/// an array-like struct that has a fixed maximum capacity
/// any element over the maximum allowed size gets discarded
struct LimitedArray<T> {
private(set) var storage: [T] = []
public let maxSize: Int
/// creates an empty array
public init(maxSize: Int) {
self.maxSize = maxSize
}
/// takes the max N elements from the given collection
public init<S: Sequence>(from other: S, maxSize: Int)
where S.Element == T, S.SubSequence: Sequence, S.SubSequence.Element == T {
self.maxSize = maxSize
storage = Array(other.prefix(maxSize))
}
/// adds a new item to the array, does nothing if the array has reached its maximum capacity
/// returns a bool indicated the operation success
@discardableResult public mutating func append(_ item: T) -> Bool {
if storage.count < maxSize {
storage.append(item)
return true
} else {
return false
}
}
/// inserts an item at the specified position. if this would result in
/// the array exceeding its maxSize, the extra element are dropped
public mutating func insert(_ item: T, at index: Int) {
storage.insert(item, at: index)
if storage.count > maxSize {
storage.remove(at: maxSize)
}
}
// add here other methods you might need
}
// let's benefit all the awesome operations like map, flatMap, reduce, filter, etc
extension LimitedArray: MutableCollection {
public var startIndex: Int { return storage.startIndex }
public var endIndex: Int { return storage.endIndex }
public subscript(_ index: Int) -> T {
get { return storage[index] }
set { storage[index] = newValue }
}
public func index(after i: Int) -> Int {
return storage.index(after: i)
}
}
由于结构符合Collection
,因此您可以通过将其内容转换为数组来轻松地将其传递给只知道使用数组的代码:Array(myLimitedArray)
。
答案 1 :(得分:0)
在追加新元素之前简单地计算数组的元素。
var array :[Int] = [1,2,3,4,5,6,7,8,9,10]
func insertIntoArray(_ value: Int, array: [Int]) -> [Int] {
var arr = array
if arr.count == 10 {
arr.removeLast()
}
arr.append(value)
return arr
}
array = insertIntoArray(11, array: array)
答案 2 :(得分:0)
你的问题的答案是否定的。 Swift没有固定大小的数组数据结构,也不需要。
如果你想为自己创建一个固定大小的数组,Ray Wenderlich has published an interesting tutorial/article关于如何在Swift中做到这一点!
答案 3 :(得分:0)
我最近想要这种确切的收藏类型。我继续创建了这个。它应该可以通过其他辅助功能来完全满足您的要求。
https://gist.github.com/djk12587/ea6d8dea837f8274b911deb0c819f74f
struct CappedCollection<T> {
private var elements: [T]
var maxCount: Int
init(elements: [T], maxCount: Int) {
self.elements = elements
self.maxCount = maxCount
}
}
extension CappedCollection: Collection, ExpressibleByArrayLiteral {
typealias Index = Int
typealias Element = T
init(arrayLiteral elements: Element...) {
self.elements = elements
maxCount = elements.count
}
var startIndex: Index { return elements.startIndex }
var endIndex: Index { return elements.endIndex }
subscript(index: Index) -> Iterator.Element {
get { return elements[index] }
}
func index(after i: Index) -> Index {
return elements.index(after: i)
}
@discardableResult
mutating func append(_ newElement: Element) -> Element? {
elements.append(newElement)
return removeExtraElements().first
}
@discardableResult
mutating func append<C>(contentsOf newElements: C) -> [Element] where C : Collection, CappedCollection.Element == C.Element {
elements.append(contentsOf: newElements)
return removeExtraElements()
}
@discardableResult
mutating func insert(_ newElement: Element, at i: Int) -> Element? {
elements.insert(newElement, at: i)
return removeExtraElements().first
}
@discardableResult
mutating func insert<C>(contentsOf newElements: C, at i: Int) -> [Element] where C : Collection, CappedCollection.Element == C.Element {
elements.insert(contentsOf: newElements, at: i)
return removeExtraElements()
}
private mutating func removeExtraElements() -> [Element] {
guard elements.count > maxCount else { return [] }
var poppedElements: [Element] = []
poppedElements.append(contentsOf: elements[maxCount..<elements.count])
elements.removeLast(elements.count - maxCount)
return poppedElements
}
}