【问题标题】:Iterate over two arrays simultaneously同时迭代两个数组
【发布时间】:2015-05-26 21:10:27
【问题描述】:

我是 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]);
}

我在 swift 中有几个数组

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 相同或更长(在您拥有的硬编码数组中有效,但在数组可能更改的代码中) , 不会工作)。
  • 是的,java代码只是一个例子。我们检查 strArr1.length == strArr2.length,否则返回。

标签: arrays swift iteration


【解决方案1】:
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])
}

【讨论】:

  • C 风格的 for 循环在 Swift 3.0 中已弃用。
  • 感谢@PopKernel,在 Swift 3.0 发布之前发布。
  • 我不是在批评,只是为其他人添加该信息
  • 没想到你是。 @PopKernel
【解决方案2】:

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

斯威夫特 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() 进行了更改。
  • 如果第一个数组的元素多于第二个数组,此代码将崩溃。您应该在 for 循环的开头添加 guard strArr2.indices.contains(index) else { break } 以使其安全。
【解决方案3】:

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

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

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

【讨论】:

  • 或更短:for i in 0..
【解决方案4】:

您可以使用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 语法,但最后一点听起来像 zip 是 Swift 2 语法。
  • @DuncanC:你说得对,最后的编辑具有误导性。 zip() 函数在 Swift 1.2 和 Swift 2 中都有效,只是底层序列类型从 Zip2 更改为 Zip2Sequence。 – 它需要两个序列(数组只是一种特殊情况)并返回一个(惰性求值的)序列,其中包含公共元素的元组。
  • 我们可以打印两个不同大小数组的所有元素吗?
  • 为什么它们都必须具有相同的类型?这似乎是一个毫无意义的限制编辑:我的问题与类型无关;无论如何都会给我同样的错误:无法使用类型为“([Float],[Float],[Float])'的参数列表调用'zip'
  • @pete:Swift zip 函数将正好两个序列作为参数,在 Swift 论坛中比较 stackoverflow.com/a/48753610/1187415forums.swift.org/t/zip3-zip4/218
【解决方案5】:

试试这个:

zip([0,2,4,6], [1,3,5,7]).forEach {
    print($0,$1)
}

zip([0,2,4,6], [1,3,5,7]).forEach {
    print($0.0,$0.1)
}

【讨论】:

  • 太棒了!这也适用于不同大小的数组
【解决方案6】:

使用 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
 */

【讨论】:

  • 爱拉链!从来不知道……我总是使用计数器来遍历循环……我和我的 C 编码技能哈哈!
【解决方案7】:
> 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"]

【讨论】:

  • 请更新您的回答。如果你不知道数组的大小,那么它就不会起作用。
猜你喜欢
  • 2016-05-16
  • 2021-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多