同时迭代两个数组


74

我是Swift的新手。我一直在做Java编程。我有一个场景可以在Swift中进行编码。

以下代码是Java语言。在以下情况下,我需要在Swift中进行编码

// With String array - strArr1
String strArr1[] = {"Some1","Some2"}

String strArr2[] = {"Somethingelse1","Somethingelse2"}

for( int i=0;i< strArr1.length;i++){
    System.out.println(strArr1[i] + " - "+ strArr2[i]);
}

我很快有几个数组

var strArr1: [String] = ["Some1","Some2"]
var strArr2: [String] = ["Somethingelse1","Somethingelse2"]

for data in strArr1{
    println(data)
}

for data in strArr2{
    println(data)
}
// I need to loop over in single for loop based on index.

您能否提供有关基于索引的循环语法的帮助?


您的Java代码开头并不安全,因为它假定strArr2的长度等于或大于StrArr1的长度(在您具有硬编码的数组中可以使用,但在可能更改数组的代码中不能使用)。
Will M.

是的,Java代码只是一个示例。我们检查一下strArr1.length == strArr2.length,否则返回。
Lohith 2015年

Answers:


142

您可以使用zip(),从两个给定的序列中创建一个成对的序列:

let strArr1 = ["Some1", "Some2"]
let strArr2 = ["Somethingelse1", "Somethingelse2"]

for (e1, e2) in zip(strArr1, strArr2) {
    print("\(e1) - \(e2)")
}

该序列仅枚举给定序列/数组的“公共元素”。如果它们的长度不同,则将忽略较长数组/序列中的其他元素。


那么zip()接受2个数组,并在两个数组中返回一个公共元素元组的数组?是zip()swift 2语法还是zip2?您的第一句话暗示这zip是swift 1.2语法,但是最后一点听起来像是zipSwift 2语法。
Duncan C

@DuncanC:是的,最后一次编辑是令人误解的。该zip()函数在Swift 1.2和Swift 2中均可使用,只有基础序列类型从更改Zip2Zip2Sequence。–它接受两个序列(数组只是一种特殊情况),并返回一个(延迟计算的)序列以及公共元素的元组。
Martin R

我们可以打印两个大小不同的数组的所有元素吗?
pankaj nigam,

为什么它们都必须具有相同的类型?似乎没有意义的限制编辑:我的问题与类型无关;它与类型无关。无论如何还是给了我同样的错误:无法使用类型为(([Float],[Float],[Float]))的参数列表调用'
zip'–彼得

1
@pete:Swiftzip函数使用两个序列作为参数,在Swift论坛中,比较stackoverflow.com/a/48753610/1187415forums.swift.org/t/zip3-zip4/218
Martin R

24

使用Swift 5,您可以使用以下4个Playground代码之一来解决您的问题。


#1 使用zip(_:_:)功能

在最简单的情况下,您可以zip(_:_:)用来创建初始数组中元素对的新序列(元组)。

let strArr1 = ["Some1", "Some2", "Some3"]
let strArr2 = ["Somethingelse1", "Somethingelse2"]

let sequence = zip(strArr1, strArr2)

for (el1, el2) in sequence {
    print("\(el1) - \(el2)")
}

/*
 prints:
 Some1 - Somethingelse1
 Some2 - Somethingelse2
 */

#2。使用ArraymakeIterator()方法和while循环

使用简单的while循环和迭代器,同时循环两个数组也很容易:

let strArr1 = ["Some1", "Some2", "Some3"]
let strArr2 = ["Somethingelse1", "Somethingelse2"]

var iter1 = strArr1.makeIterator()
var iter2 = strArr2.makeIterator()

while let el1 = iter1.next(), let el2 = iter2.next() {
    print("\(el1) - \(el2)")
}

/*
 prints:
 Some1 - Somethingelse1
 Some2 - Somethingelse2
 */

#3。使用符合以下条件的自定义类型IteratorProtocol

在某些情况下,您可能需要创建自己的类型,以将姓名缩写数组的元素配对。可以通过使您的类型符合来实现IteratorProtocol。请注意,通过使您的类型也符合Sequence协议,您可以在for循环中直接使用它的实例:

struct TupleIterator: Sequence, IteratorProtocol {

    private var firstIterator: IndexingIterator<[String]>
    private var secondIterator: IndexingIterator<[String]>

    init(firstArray: [String], secondArray: [String]) {
        self.firstIterator = firstArray.makeIterator()
        self.secondIterator = secondArray.makeIterator()
    }

    mutating func next() -> (String, String)? {
        guard let el1 = firstIterator.next(), let el2 = secondIterator.next() else { return nil }
        return (el1, el2)
    }

}

let strArr1 = ["Some1", "Some2", "Some3"]
let strArr2 = ["Somethingelse1", "Somethingelse2"]

let tupleSequence = TupleIterator(firstArray: strArr1, secondArray: strArr2)

for (el1, el2) in tupleSequence {
    print("\(el1) - \(el2)")
}

/*
 prints:
 Some1 - Somethingelse1
 Some2 - Somethingelse2
 */

#4。使用AnyIterator

作为上一个示例的替代方法,您可以使用AnyIterator。以下代码显示了在Array扩展方法中可能的实现:

extension Array {

    func pairWithElements(of array: Array) -> AnyIterator<(Element, Element)> {
        var iter1 = self.makeIterator()
        var iter2 = array.makeIterator()

        return AnyIterator({
            guard let el1 = iter1.next(), let el2 = iter2.next() else { return nil }
            return (el1, el2)
        })
    }

}

let strArr1 = ["Some1", "Some2", "Some3"]
let strArr2 = ["Somethingelse1", "Somethingelse2"]

let iterator = strArr1.pairWithElements(of: strArr2)

for (el1, el2) in iterator {
    print("\(el1) - \(el2)")
}

/*
 prints:
 Some1 - Somethingelse1
 Some2 - Somethingelse2
 */


14

您还可以enumerate遍历一个数组,并使用索引查看第二个数组:

Swift 1.2:

for (index, element) in enumerate(strArr1) {
    println(element)
    println(strArr2[index])
}

斯威夫特2:

for (index, element) in strArr1.enumerate() {
    print(element)
    print(strArr2[index])
}

斯威夫特3:

for (index, element) in strArr1.enumerated() {
    print(element)
    print(strArr2[index])
}

在最新版本的swift中,对strArr1.enumerate()进行了更改。
robhasacamera'3

如果第一个数组比第二个数组包含更多元素,则此代码将崩溃。您应该guard strArr2.indices.contains(index) else { break }在for循环的开头添加以使其安全。
Imanou Petit

0

你可以使用Range,如果你仍然想使用for in

var strArr1: [String] = ["Some1","Some2"]
var strArr2: [String] = ["Somethingelse1","Somethingelse2"]

for i in Range(start: 0, end: strArr1.count) {
    println(strArr1[i] + " - " + strArr2[i])
}

或更短:对于0中的i。.<strArr1.count {...}
何塞·拉米雷斯

0
for(var i = 0; i < strArr1.count ; i++)
{
    println(strArr1[i] + strArr2[i])
}

那应该做。之前从未使用过Swift,因此请务必进行测试。

更新为最新的Swift语法

for i in 0..< strArr1.count {
    print(strArr1[i] + strArr2[i])
}

4
Swift 3.0不推荐使用C样式的循环。
PopKernel

感谢@PopKernel,在Swift 3.0发布之前发布了此内容。
埃里克

1
我并不是在批评,只是为其他人添加了该信息
-PopKernel

1
没想到你是。@PopKernel
Erik

0
> Incase of unequal count 

let array1 = ["some1","some2"]
let array2 = ["some1","some2","some3"]

var iterated = array1.makeIterator()
let finalArray = array2.map({ 
                 let itemValue = iterated.next()
                 return "\($0)\(itemValue != nil ? "-"+itemValue! : EmptyString)" })

//结果:[“ some1-some1”,“ some2-some2”,“ some3”]


请更新您的答案。如果您不知道数组的大小,那么它将不起作用。
Anup Gupta,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.