我正在尝试找出使用SWIFT 4遍历数字数组,获取任何连续数字范围并将其添加到新数组中的最有效方法。我可以进行标准循环检查,但是我可以使用地图过滤器吗? -有人可以指出正确的方向吗?
开始:
myNumbersArray:[Int] = [1,2,3,4,10,11,15,20,21,22,23]
想要的结果:
newNumbersArray = [
[1,2,3,4],
[10,11],
[15],
[20,21,22,23]
]
如果解决了,我将发布解决方案...
答案 0 :(得分:9)
我的建议是IndexSet
,其中将连续项目存储为范围。
rangeView
。let myNumbersArray = [1,2,3,4,10,11,15,20,21,22,23]
let indexSet = IndexSet(myNumbersArray)
let rangeView = indexSet.rangeView
let newNumbersArray = rangeView.map { Array($0.indices) }
答案 1 :(得分:4)
虽然根据@vadian使用IndexSet
是个好主意,但它仅在您的情况下有效(连续和正整数),使用索引可能不是您的目的。为此,使用类似的对象有点麻烦,但是做得很好。
一种可能的方法是使用reduce()
:
let reduced = myNumbersArray.reduce([[Int]]()) { (current, next) -> [[Int]] in
var result = current
//Retrieve the last sequence, check if the current - last item of sequence is 1 to know if they are consecutive or not
if var lastSequence = result.last, let last = lastSequence.last, next-last == 1 {
lastSequence.append(next)
result[result.endIndex-1] = lastSequence
return result
} else { //It's not => New array of its own
result.append([next])
return result
}
}
print("reduced: \(reduced)")
输出:
$>reduced: [[1, 2, 3, 4], [10, 11], [15], [20, 21, 22, 23]]
根据@Leo Dabus的建议,使用reduce(into:)
:
let reducedInto = myNumbersArray.reduce(into: [[Int]]()) { (result, next) in
//Retrieve the last sequence, check if the current - last item of sequence is 1
if var lastSequence = result.last, let last = lastSequence.last, next-last == 1 {
lastSequence.append(next)
result[result.endIndex-1] = lastSequence
} else { //It's not => New array of its own
result.append([next])
}
}
print("reducedInto: \(reducedInto)")
输出:
$>reducedInto: [[1, 2, 3, 4], [10, 11], [15], [20, 21, 22, 23]]
答案 2 :(得分:4)
这对于负整数也适用:
extension BidirectionalCollection where Element: BinaryInteger, Index == Int {
var consecutivelyGrouped: [[Element]] {
return reduce(into: []) {
$0.last?.last?.advanced(by: 1) == $1 ?
$0[index(before: $0.endIndex)].append($1) :
$0.append([$1])
}
}
}
let numbers = [-5,-4,-2,0,1,3,4,10,11,15,20,21,22,23]
let grouped = numbers.consecutivelyGrouped // [[-5, -4], [-2], [0, 1], [3, 4], [10, 11], [15], [20, 21, 22, 23]]
答案 3 :(得分:0)
对于不熟悉地图和索引集的用户,请检查以下内容:
var arr = [0,1,2,4,6,7,9]
var previousIndex = 0
var count = 0
var arrayDict : [Int:[Int]] = [:]
for (index,data) in arr.enumerated() {
if index == (arr.count - 1) {
arrayDict[count] = Array(arr[previousIndex ..< index + 1])
break
}
if arr[index + 1] - data != 1 {
arrayDict[count] = Array(arr[previousIndex ..< index + 1])
previousIndex = index + 1
count += 1
}
}
print(arrayDict)
逻辑是,我要遍历给定数组的元素,并且每次检查该索引处的值是否不小于索引+ 1的值乘以1(如果是的话),则使用数组切片并将其添加到具有键的字典中,该键由变量“ count”给出。变量previous index保留上一个拆分的结束索引,以便下一个拆分从previousIndex到当前索引开始