在Swift中一次迭代两个集合
假设我有一个数组在Swift中一次迭代两个集合,swift,Swift,假设我有一个数组[1,2,3,4,5]。如何一次迭代两次 Iteration 1: (1, 2) Iteration 2: (3, 4) Iteration 3: (5, nil) 如果数组的元素数为偶数,则可以编写如下内容: for i in 0..<arr.count/2 { print(arr[2*i...2*i+1]) } 更新以上两种解决方案都可以通过使用map而不是手动循环来简化: let pairs = (0..<arr.count/2).map { (ar
[1,2,3,4,5]
。如何一次迭代两次
Iteration 1: (1, 2)
Iteration 2: (3, 4)
Iteration 3: (5, nil)
如果数组的元素数为偶数,则可以编写如下内容:
for i in 0..<arr.count/2 {
print(arr[2*i...2*i+1])
}
更新以上两种解决方案都可以通过使用map
而不是手动循环来简化:
let pairs = (0..<arr.count/2).map { (arr[$0*2], arr[$0*2+1]) }
print(pairs) // prints [(1, 2), (3, 4)]
您可以扩展集合
,使此对
功能可用于所有集合:
extension Collection {
func pairs() -> [(Element, Element?)] {
guard !isEmpty else { return [] }
return (0..<count/2+count%2).map {
let i1 = index(startIndex, offsetBy: $0*2)
let i2 = index(after: i1)
return (self[i1], i2 < endIndex ? self[i2] : nil)
}
}
}
扩展集合{
func pairs()->[(元素,元素?]{
守卫!我没有其他{return[]}
return(0..一种方法是将数组封装在一个类中。获取项目对的返回值是可选的,以防止超出范围的调用
例如:
class Pairs {
let source = [1, 2, 3, 4, 5] // Or set with init()
var offset = 0
func nextpair() -> (Int?, Int?) {
var first: Int? = nil
var second: Int? = nil
if offset < source.count {
first = source[offset]
offset++
}
if offset < source.count {
second = source[offset]
offset++
}
return (first, second)
}
}
let seq = (1...).prefix(5)
for pair in seq.pairs() { print(pair) }
类对{
让source=[1,2,3,4,5]//或用init()设置
var偏移量=0
func nextpair()->(Int?,Int?){
第一个变量:Int?=nil
第二个变量:Int?=nil
如果偏移量
我个人不喜欢在一半的列表中循环(主要是因为划分),所以我喜欢这样做:
let array = [1,2,3,4,5];
var i = 0;
while i < array.count {
var a = array[i];
var b : Int? = nil;
if i + 1 < array.count {
b = array[i+1];
}
print("(\(a), \(b))");
i += 2;
}
let数组=[1,2,3,4,5];
var i=0;
而我
通过递增2循环数组
如果希望元素中有nil,则需要使用可选项。您可以使用称为stride(to:,by:)的渐进循环,每n个元素迭代一次元素:
let array = Array(1...5)
let pairs = stride(from: 0, to: array.endIndex, by: 2).map {
(array[$0], $0 < array.index(before: array.endIndex) ? array[$0.advanced(by: 1)] : nil)
} // [(.0 1, {some 2}), (.0 3, {some 4}), (.0 5, nil)]
print(pairs) // "[(1, Optional(2)), (3, Optional(4)), (5, nil)]\n"
这将适用于任何类型的收藏:
let string = "12345"
for substring in string.unfoldSubSequences(limitedTo: 2) {
print(substring) // "12" "34" "5"
}
您可以使用sequence()
和迭代器的next()
方法进行迭代
在成对的连续元素上。这适用于任意序列,
不仅是阵列:
let a = "ABCDE"
for pair in sequence(state: a.makeIterator(), next: { it in
it.next().map { ($0, it.next()) }
}) {
print(pair)
}
输出:
("A", Optional("B"))
("C", Optional("D"))
("E", nil)
例如:
class Pairs {
let source = [1, 2, 3, 4, 5] // Or set with init()
var offset = 0
func nextpair() -> (Int?, Int?) {
var first: Int? = nil
var second: Int? = nil
if offset < source.count {
first = source[offset]
offset++
}
if offset < source.count {
second = source[offset]
offset++
}
return (first, second)
}
}
let seq = (1...).prefix(5)
for pair in seq.pairs() { print(pair) }
请注意,这些对是惰性生成的,没有中间数组
如果您想要一个包含所有对的数组,那么
let pairs = Array([1, 2, 3, 4, 5].pairs())
print(pairs) // [(1, Optional(2)), (3, Optional(4)), (5, nil)]
做这项工作。这与所问的问题不同,但我使用了序列扩展,它生成一个数组,将原始序列按任意所需大小分块:
extension Sequence {
func clump(by clumpsize:Int) -> [[Element]] {
let slices : [[Element]] = self.reduce(into:[]) {
memo, cur in
if memo.count == 0 {
return memo.append([cur])
}
if memo.last!.count < clumpsize {
memo.append(memo.removeLast() + [cur])
} else {
memo.append([cur])
}
}
return slices
}
}
扩展序列{
func clump(按clumpsize:Int)->[[Element]]{
让切片:[[Element]]=self.reduce(变成:[]){
备忘录,请进来
如果memo.count==0{
返回备忘录。附加([cur])
}
如果memo.last!.count
所以[1,2,3,4,5].clump(by:2)
产生[[1,2],[3,4],[5]
,现在,如果您愿意,您可以迭代它。扩展以拆分数组
extension Array {
func chunked(into size: Int) -> [[Element]] {
return stride(from: 0, to: count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, count)]) }
}
}
let result = [1...10].chunked(into: 2)
扩展数组{
func分块(分为大小:Int)->[[Element]]{
返回步幅(从:0到:计数,按:大小)。映射{
数组(self[$0..
这是我的解决方案,其中包括一个reduce
和几个guard
s
extension Array {
var touplesOfTwo: [(Element,Element?)] {
self.reduce(into: [(Element,Element?)]()) {
guard let last = $0.last else { $0.append( ($1,nil) ); return }
let lastIndex = $0.count - 1
guard let _ = last.1 else { $0[lastIndex].1 = $1; return }
$0.append( ($1,nil) )
}
}
}
let list = [1,4,3,7,2,9,6,5]
let queues = list.map { $0 }
let touplesList = queues.touplesOfTwo
print("\(touplesList)")
// [(1, Optional(4)), (3, Optional(7)), (2, Optional(9)), (6, Optional(5))]
您应该将a声明为let,因为它的值不会更改。注意:考虑到输入数组只有整数(Int),因此它永远不会为零,所以元组的第一个元素不需要是可选的,因此您可以将其声明为[(Int,Int?]酷!对于不能用整数索引的东西怎么样?@fumoboy007我不知道你可以有一个不能用整数nvm索引的数组。任何值得一次迭代两次的东西都会有一个可移动的@PaulBrewczynski的索引。如果处理基因与否没有任何区别。只是个人偏好erence(语法)。如果这让你感到不安,就把它改为+1。当然,真正的目标是实现ruby的每个片段
,我们不限于成对,而是可以将一个序列分为任意给定长度的子序列(三元组等)。@matt:类似于?我发布了这个答案,因为这里的请求是填充“不完整”用nil而不是截断块,但是是的,它非常相似。太好了,我希望你会有这样的东西!非常干净!一个问题:你不需要在it.next().map{}
中使用可选链接吗,因为it.next()
返回一个可选的?@fumoboy007不,这就是为什么不简单地让i2=index(在:i1之后)是的,那会更简单,@LeoDabuslet queues=list.map{$0}
是无意义的sbtw Swift是一种类型推断语言reduce(to:[])
并且不需要使用两个保护语句。guard let last=$0.last,last.1==nil else{
<0.append($1,nil))
正是我需要的!谢谢。
extension Sequence {
func clump(by clumpsize:Int) -> [[Element]] {
let slices : [[Element]] = self.reduce(into:[]) {
memo, cur in
if memo.count == 0 {
return memo.append([cur])
}
if memo.last!.count < clumpsize {
memo.append(memo.removeLast() + [cur])
} else {
memo.append([cur])
}
}
return slices
}
}
extension Array {
func chunked(into size: Int) -> [[Element]] {
return stride(from: 0, to: count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, count)]) }
}
}
let result = [1...10].chunked(into: 2)
extension Array {
var touplesOfTwo: [(Element,Element?)] {
self.reduce(into: [(Element,Element?)]()) {
guard let last = $0.last else { $0.append( ($1,nil) ); return }
let lastIndex = $0.count - 1
guard let _ = last.1 else { $0[lastIndex].1 = $1; return }
$0.append( ($1,nil) )
}
}
}
let list = [1,4,3,7,2,9,6,5]
let queues = list.map { $0 }
let touplesList = queues.touplesOfTwo
print("\(touplesList)")
// [(1, Optional(4)), (3, Optional(7)), (2, Optional(9)), (6, Optional(5))]