我试图解决这个挑战:给定一个组大小的组反转一组元素。
给定数组:[1,2,3,4,5,6]
期望的结果(组大小为3):[4,5,6,1,2,3]
如果最后一组的元素少于组大小,则只需添加它们并完成,如下所示:
给定数组:[1,2,3,4,5,6,7]
期望的结果:[5,6,7,2,3,4,1]
我试过这个并且它正在工作,但对我来说它看起来有点奇怪。任何人都可以帮我找到更清洁或更直观的解决方案吗?
extension Array {
func reverse(groupSize: Int) -> [Element] {
var reversed = [Element]()
let groups = count / groupSize
for group in 0...groups {
let lowerBound = count - group * groupSize - groupSize
let upperBound = count - 1 - group * groupSize
if lowerBound >= 0 {
reversed += Array(self[lowerBound...upperBound])
} else {
reversed += Array(self[0...upperBound])
}
}
return reversed
}
}
答案 0 :(得分:2)
以下解决方案基于stride
+ map
:
let groupSize = 3
let array = [1, 2, 3, 4, 5, 6]
let reversedArray = Array(array.reversed())
let result = stride(from: 0, to: reversedArray.count, by: groupSize).map {
reversedArray[$0 ..< min($0 + groupSize, reversedArray.count)].reversed()
}.reduce([Int](), +)
print(result) // [4, 5, 6, 1, 2, 3]
答案 1 :(得分:1)
我认为你的功能没问题,不确定你的意思是什么奇怪的tbh,可以分离到块或者以相反的方式添加每个元素,但逻辑是相同的,只需要考虑每种方式的性能/复杂性:< / p>
let a = [1,2,3,4,5,6,7,8,9,10,11]
extension Array {
func reverse(group: Int) -> [Element] {
guard group > 1 else { return self.reversed() }
var new = [Element]()
for i in stride(from: self.count-1, through: 0, by: -group) {
let k = i-group+1 < 0 ? 0 : i-group+1
for j in k...i {
new.append(self[j])
}
}
return new
}
}
a.reverse(group: 4) //[8, 9, 10, 11, 4, 5, 6, 7, 1, 2, 3]
答案 2 :(得分:1)
你可以说:
extension Array {
func groupedReversing(stride: Int) -> [Element] {
precondition(stride > 0, "stride must be > 0")
return Swift.stride(from: count, to: 0, by: -stride)
.flatMap { self[Swift.max(0, $0 - stride) ..< $0] }
}
}
let result = Array(1 ... 7).groupedReversing(stride: 3)
print(result) // [5, 6, 7, 2, 3, 4, 1]
我们正在使用stride(from:through:by:)
以(减去)步幅的增量从array.count
(包括)到0
(不包括)进行迭代。 Swift.
前缀是为了将其从过时的Swift 2 stride
方法(will be gone in Swift 4.1)中消除歧义。
然后,我们将索引平面映射到输入数组的切片,该切片长达stride
个元素(在我们将较低的索引钳位为0时截断数组的开头)。因为这是flatMap
,所以生成的切片会连接成一个结果数组。
您还可以在Sequence
之间实现一个完全通用的版本,首先在BidirectionalCollection
上提供一个实现,向后推进索引并将切片附加到结果数组中:
extension BidirectionalCollection {
func groupedReversing(stride: Int) -> [Element] {
precondition(stride > 0, "stride must be > 0")
var result: [Element] = []
result.reserveCapacity(numericCast(count))
var upper = endIndex
while upper != startIndex {
// get the next lower bound for the slice, stopping at the start index.
let lower = index(upper, offsetBy: -numericCast(stride),
limitedBy: startIndex) ?? startIndex
result += self[lower ..< upper]
upper = lower
}
return result
}
}
然后在Sequence
上实现首先转换为数组的重载,然后转发到上面的实现:
extension Sequence {
func groupedReversing(stride: Int) -> [Element] {
return Array(self).groupedReversing(stride: stride)
}
}
现在您可以调用它,例如CountableClosedRange
,而无需先将其转换为数组:
let result = (1 ... 7).groupedReversing(stride: 3)
print(result) // [5, 6, 7, 2, 3, 4, 1]
答案 3 :(得分:0)
以下两个Swift 4.1代码段显示了如何实现Collection
或Array
扩展方法以便对其进行分块,反转它然后将其展平为新数组。
AnyIterator
和Sequence
joined()
extension Collection {
func reverseFlattenChunked(by distance: Int) -> [Element] {
precondition(distance > 0, "distance must be greater than 0")
var index = endIndex
let iterator = AnyIterator({ () -> SubSequence? in
let newIndex = self.index(index, offsetBy: -distance, limitedBy: self.startIndex) ?? self.startIndex
defer { index = newIndex }
return index != self.startIndex ? self[newIndex ..< index] : nil
})
return Array(iterator.joined())
}
}
用法:
let array = ["1", "2", "3", "4", "5", "6", "7"]
let newArray = array.reverseFlattenChunked(by: 3)
print(newArray) // prints: ["5", "6", "7", "2", "3", "4", "1"]
let array: [String] = ["1", "2", "3", "4", "5", "6"]
let newArray = array.reverseFlattenChunked(by: 2)
print(newArray) // prints: ["5", "6", "3", "4", "1", "2"]
let array: [String] = []
let newArray = array.reverseFlattenChunked(by: 3)
print(newArray) // prints: []
stride(from:to:by:)
和Sequence
flatMap(_:)
extension Array {
func reverseFlattenChunked(by distance: Int) -> [Element] {
precondition(distance > 0, "distance must be greater than 0")
let indicesSequence = stride(from: self.endIndex, to: self.startIndex, by: -distance)
let array = indicesSequence.flatMap({ (index) -> SubSequence in
let advancedIndex = self.index(index, offsetBy: -distance, limitedBy: self.startIndex) ?? self.startIndex
// let advancedIndex = index.advanced(by: -distance) <= self.startIndex ? self.startIndex : index.advanced(by: -distance) // also works
return self[advancedIndex ..< index]
})
return array
}
}
用法:
let array = ["1", "2", "3", "4", "5", "6", "7"]
let newArray = array.reverseFlattenChunked(by: 3)
print(newArray) // prints: ["5", "6", "7", "2", "3", "4", "1"]
let array: [String] = ["1", "2", "3", "4", "5", "6"]
let newArray = array.reverseFlattenChunked(by: 2)
print(newArray) // prints: ["5", "6", "3", "4", "1", "2"]
let array: [String] = []
let newArray = array.reverseFlattenChunked(by: 3)
print(newArray) // prints: []