Iterieren Sie über zwei Arrays gleichzeitig


73

Ich bin neu bei Swift. Ich habe Java programmiert. Ich muss in Swift ein Szenario codieren.

Der folgende Code ist in Java. Ich muss in Swift für das folgende Szenario codieren

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

Ich habe ein paar Arrays in Kürze

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.

Könnten Sie bitte Ihre Hilfe zu den Syntaxen für das Schleifen basierend auf dem Index bereitstellen?


Ihr Java-Code ist zunächst unsicher, da davon ausgegangen wird, dass strArr2 dieselbe Länge oder länger als StrArr1 hat (was in den hartcodierten Arrays, die Sie haben, funktioniert, aber in Code, in dem sich die Arrays ändern könnten, nicht funktioniert).
Will M.

Ja, der Java-Code ist nur ein Beispiel. Wir prüfen, ob strArr1.length == strArr2.length ist, sonst kehren wir zurück.
Lohith

Antworten:


140

Sie können verwenden zip(), wodurch eine Folge von Paaren aus den beiden angegebenen Folgen erstellt wird:

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

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

Die Sequenz zählt nur die "gemeinsamen Elemente" der gegebenen Sequenzen / Arrays auf. Wenn sie unterschiedlich lang sind, werden die zusätzlichen Elemente des längeren Arrays / der längeren Sequenz einfach ignoriert.


Also nimmt zip () 2 Arrays und gibt ein Array von Tupeln gemeinsamer Elemente in beiden Arrays zurück? Ist zip()Swift 2 Syntax oder ist zip2? Ihr erster Satz impliziert, dass dies zipdie schnelle 1.2-Syntax ist, aber das letzte Bit lässt es so klingen, als wäre zipes die Swift 2-Syntax.
Duncan C

@ DuncanC: Sie haben Recht, die letzte Änderung war irreführend. Die zip()Funktion funktioniert sowohl in Swift 1.2 als auch in Swift 2, nur der zugrunde liegende Sequenztyp wurde von Zip2nach geändert Zip2Sequence. - Es werden zwei Sequenzen benötigt (Arrays sind nur ein Sonderfall) und eine (träge ausgewertete) Sequenz mit den Tupeln der gemeinsamen Elemente zurückgegeben.
Martin R

Können wir alle Elemente eines Arrays mit zwei verschiedenen Größen drucken?
Pankaj Nigam

Warum müssen alle den gleichen Typ haben? Es scheint eine sinnlose Einschränkung zu sein. Bearbeiten: Mein Problem hing nicht mit dem Typ zusammen. gibt mir sowieso den gleichen Fehler: 'zip' kann nicht mit einer Argumentliste vom Typ '([Float], [Float], [Float])'
pete

1
@pete: Die Swift- zipFunktion verwendet genau zwei Sequenzen als Argumente: Compare stackoverflow.com/a/48753610/1187415 oder forums.swift.org/t/zip3-zip4/218 im Swift-Forum.
Martin R

22

Mit Swift 5 können Sie einen der 4 folgenden Spielplatzcodes verwenden, um Ihr Problem zu lösen.


# 1. Mit zip(_:_:)Funktion

Im einfachsten Fall können Sie zip(_:_:)eine neue Folge von Paaren (Tupel) der Elemente Ihrer anfänglichen Arrays erstellen.

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. Mit Arrayder makeIterator()Methode von und einer while-Schleife

Es ist auch einfach, zwei Arrays gleichzeitig mit einer einfachen while-Schleife und Iteratoren zu durchlaufen:

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. Verwenden eines benutzerdefinierten Typs, der den Anforderungen entsprichtIteratorProtocol

Unter bestimmten Umständen möchten Sie möglicherweise einen eigenen Typ erstellen, der die Elemente Ihrer Initialen-Arrays koppelt. Dies ist möglich, indem Sie Ihren Typ anpassen IteratorProtocol. Beachten Sie, dass SequenceSie Instanzen davon direkt in einer for-Schleife verwenden können , indem Sie Ihren Typ auch an das Protokoll anpassen :

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. Verwenden vonAnyIterator

Alternativ zum vorherigen Beispiel können Sie verwenden AnyIterator. Der folgende Code zeigt eine mögliche Implementierung innerhalb einer ArrayErweiterungsmethode:

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

19

Versuche dies:

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)
}

groß! Dies funktioniert auch für Arrays mit unterschiedlichen Größen
Kamen Dobrev

14

Sie können auch enumerateüber ein Array gehen und den Index verwenden, um in das zweite Array zu schauen:

Swift 1.2:

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

Swift 2:

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

Swift 3:

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

Dies hat Änderungen an strArr1.enumerate () in der neuesten Version von swift.
Robhasacamera

Dieser Code stürzt ab, wenn das erste Array mehr Elemente als das zweite Array enthält. Sie sollten guard strArr2.indices.contains(index) else { break }am Anfang der for-Schleife hinzufügen, um die Sicherheit zu gewährleisten.
Imanou Petit

0

Sie können verwenden, Rangewenn Sie noch verwenden möchten 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])
}

Oder kürzer: für i in 0 .. <strArr1.count {...}
Jose Ramirez

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

Das sollte es tun. Nie zuvor schnell verwendet, also unbedingt testen.

Auf die aktuelle Swift-Syntax aktualisiert

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

4
C-Style für Schleifen sind in Swift 3.0 veraltet.
PopKernel

Danke @PopKernel, habe dies gepostet, bevor Swift 3.0 veröffentlicht wurde.
Erik

1
Ich habe nicht kritisiert, nur diese Informationen für andere Leute
hinzugefügt

1
Ich hätte nicht gedacht, dass du es bist. @ 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)" })

// Ergebnis: ["some1-some1", "some2-some2", "some3"]


Bitte aktualisieren Sie Ihre Ans. Wenn Sie die Größe des Arrays nicht kennen, funktioniert es nicht.
Anup Gupta
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.