【发布时间】:2017-05-29 00:04:18
【问题描述】:
假设我有一个包含 10 个元素的数组。说,
var ArrayElemts : ["1","2","3","4","5","6","7","8","9","10","11"]
现在如何将元素从 0 到 5 保留在一个数组集中,将 6 到 10 的元素保留在另一个数组集中?
【问题讨论】:
-
您的数组样本中有 11 个元素
标签: swift
假设我有一个包含 10 个元素的数组。说,
var ArrayElemts : ["1","2","3","4","5","6","7","8","9","10","11"]
现在如何将元素从 0 到 5 保留在一个数组集中,将 6 到 10 的元素保留在另一个数组集中?
【问题讨论】:
标签: swift
使用[0...5] 创建ArraySlice,然后使用Array 将其转换回数组:
var arrayElemts = ["1","2","3","4","5","6","7","8","9","10","11"]
let first = Array(arrayElemts[0...5])
let second = Array(arrayElemts[6...10])
print(first) // ["1", "2", "3", "4", "5", "6"]
print(second) // ["7", "8", "9", "10", "11"]
【讨论】:
最简单的选择如下:
let partition1 = array.filter { Int($0) ?? 0 <= 5 }
let partition2 = array.filter { Int($0) ?? 0 > 5 }
转换为数字应该是第一步。永远不要把字符串当作数字来处理。
let numbers = array.flatMap { Int($0) }
let partition1 = numbers.filter { $0 <= 5 }
let partition2 = numbers.filter { $0 > 5 }
如果我们假设数组已排序,则有更简单的选择:
let sorted = numbers.sorted()
let partition1: [Int]
let partition2: [Int]
if let partition2start = sorted.index(where: { $0 > 5 }) {
partition1 = Array(sorted.prefix(upTo: partition2start))
partition2 = Array(sorted.suffix(from: partition2start))
} else {
partition1 = sorted
partition2 = []
}
这是原生的partition 方法可以做到的:
var numbers = array.flatMap { Int($0) }
let index = numbers.partition { $0 > 5 }
let partition1 = Array(numbers.prefix(upTo: index))
let partition2 = Array(numbers.suffix(from: index))
注意该方法更改了原始数组。
【讨论】:
N 大小的块其他答案向您展示了如何使用ArraySlice:s 将原始数组“静态”划分为不同的数组。根据您的描述,通常您可能希望将原始数组分解为 N 大小的块(此处为:n = 5)。
我们可以使用sequence(state:next) 来实现这样的chunk(bySize:) 方法作为Collection 的扩展:
extension Collection {
func chunk(bySize size: IndexDistance) -> [SubSequence] {
precondition(size > 0, "Chunk size must be a positive integer.")
return sequence(
state: (startIndex, index(startIndex, offsetBy: size, limitedBy: endIndex) ?? endIndex),
next: { indices in
guard indices.0 != self.endIndex else { return nil }
indices.1 = self.index(indices.0, offsetBy: size, limitedBy: self.endIndex) ?? self.endIndex
return (self[indices.0..<indices.1], indices.0 = indices.1).0
}).map { $0 }
}
}
应用于您的示例:
var arrayElements = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]
let partitions = arrayElements.chunk(bySize: 5)
/* [["1", "2", "3", "4", "5"],
["6", "7", "8", "9", "10"],
["11"]] */
chunk(bySize:) 方法会将数组分解为bySize 大小的块,以及(可能)为最终分区的较小块。
然而,尽管我想尝试使用sequence(state:next) 函数(不需要使用除state 之外的任何可变中间变量),但上面的实现相当臃肿且难以阅读,所以(至于其他许多情况......)我们可能最好只使用while循环:
extension Collection {
func chunk(bySize size: IndexDistance) -> [SubSequence] {
precondition(size > 0, "Chunk size must be a positive integer.")
var chunks: [SubSequence] = []
var from = startIndex
while let to = index(from, offsetBy: size, limitedBy: endIndex) {
chunks.append(self[from..<to])
from = to
}
if from != endIndex { chunks.append(self[from..<endIndex]) }
return chunks
}
}
【讨论】:
lol 我不明白为什么这里有这么复杂的答案 (按原样考虑“数组”变量 -> [Int],而不是 [Any]) 因此,第一种方法仅适用于 Number 类型。 第二个应该这样做
简单地说:
let array = [0,1,2,3,4,5,6,7,8,9,10]
//For instance..
var arrayA = ["A","B","C","D","E","F","G"]
//First 6 elements
let arrayOfFirstFour = array.filter({
return $0 <= 5 ? true : false
})
//Remaining elements:
let restOfArray = array.filter({
return $0 > 5 ? true : false
})
let elementsToFourth = arrayA.prefix(upTo: 4)
let elementsAfterFourth = arrayA.suffix(from: 4)
print(arrayOfFirstFour)
print(restOfArray)
print(elementsToFourth)
print(elementsAfterFourth)
//[0, 1, 2, 3, 4, 5]
//[6, 7, 8, 9, 10]
//["A", "B", "C", "D"]
//["E", "F", "G"]
【讨论】:
let arrayOfFirstFour = array.filter{ $0 <= 5 }
["x", "a", "1", "4", "foo", "11", "3"]怎么办?我相信问题数组中元素的 values 只是示例,而问题涉及根据元素的 positions 拆分元素(而不是 values!),因此您的基于值的过滤器有些误导。 prefix 和 suffix 方法很好(正如 @Sulthan:s answer 中已经介绍的那样),因为数组将被拆分为正好两个数组(实际上不删除“拆分”元素)。