2015-02-24 19 views
3

我有三個數組,我試圖通過運行,我想在一個函數中使用來自所有三個數組的值。這聽起來令人困惑,但這裏是我:如何在同一個循環中運行三個單獨的數組?

var Name = [Joe, Sarah, Chad] 
    var Age = [18, 20, 22] 
    var Gender = [Male, Female, Male] 

    for name in Name { 
     for age in Age { 
      for gender in Gender { 
       makeUser(name, userAge: age, userGender: gender) 
      } 
     } 
    } 

這將運行,但我得到的是:(makeUser打印出3個值)

Joe, 18, Male 
Joe, 20, Male 
Joe, 22, Male 

Joe, 18, Female 
Joe, 20, Female 
Joe, 22, Female .... 

等。

我要的是

Joe, 18, Male 
Sarah, 20, Female 
Chad, 22, Male 

這可能嗎?任何幫助表示讚賞。

謝謝!

回答

4

如果你總是肯定的陣列將在長度上是平等的,那麼你最好還是通過陣列的一個循環,並用它的索引引用別人:

for (index, name) in enumerate(Name) { 
    makeUser(name, userAge: Age[index], userGender: Gender[index]) 
} 

然而,我建議將這些數據寫入字典,但我認爲這只是示例數據來說明一個觀點。 :)

0

見下文。但是,如果這些數組的大小與其他數組的大小不同,則代碼將崩潰。

var Name = ["a", "b", "c"] 
var Age = [1, 2, 3] 
var Gender = ["m", "f", "m"] 

for (var i = 0; i<Name.count; i++) { 
    var name = Name[i] 
    var age = Age[i] 
    var gender = Gender[i] 
    makeUser(name, userAge: age, userGender: gender) 
} 
15

這是一個很常見的需求,因此標準庫迎合它的功能,zip:*

for (a,b) in zip(seq1, seq2) { 
    // a and b will be matching pairs from the two sequences 
} 

遺憾的是,截至目前,zip只做對的,儘管在理論上它可能會超載做三倍。然而,這不是什麼大不了的事,你可以窩他們:

var names = ["Joe", "Sarah", "Chad"] 
var ages = [18, 20, 22] 
var genders: [Gender] = [.Male, .Female, .Male] 

for (name,(age,gender)) in zip(names,zip(ages,genders)) { 
    makeUser(name, userAge: age, userGender: gender) 
} 

注意,它只會到最短的序列,因此,如果有超過年齡或性別多個名稱,你只會得到匹配名稱。

與使用索引相比,這可能看起來不太合適,而且這看起來也許更復雜一些,但該選擇的簡單性是欺騙性的。請記住,如果您在使用indicesenumerate以及不匹配的數組的同時使用了indicesenumerate,那麼會發生什麼情況 - 您會得到一個數組越界的斷言(或者您必須放入檢查邏輯)。

zip可以避免這個問題。這也意味着您可以使用序列而不是集合,也可以使用沒有整數索引的集合(不像enumerate)或具有不同索引類型的集合(例如StringArray)。

*(在目前的測試版,反正 - zip返回Zip2對象在雨燕1.1,您需要創建Zip2版本直接作爲zip纔剛剛被引入)

0

,就可以把枚舉作爲數組並使用函數方法將結果映射到您想要的內容。

var Name = ["a", "b", "c"] 
var Age = [1, 2, 3] 
var Gender = ["m", "f", "m"] 

let results = Array(Name.enumerated()) 
    .map {($0.element, Age[$0.index], Gender[$0.index])} 
+0

請補充點兒回答如上。 – 2016-11-10 09:03:43

0

下面是使用zip 3陣列的解決方案(測試他們確實是相同的長度):

for (name, (age, gender)) in zip(names, zip(ages, genders)) { 
    makeUser(name, userAge: age, userGender: gender) 
} 

但也許最乾淨的他們都只是老式的C風格:

for i in 0..<names.count { 
    let name = names[i] 
    let age = ages[i] 
    let gender = genders[i] 
    makeUser(name, userAge: age, userGender: gender) 
} 
0

您可以使用自定義的zip3函數,該函數不難編寫。

struct Zip3Sequence<E1, E2, E3>: Sequence, IteratorProtocol { 
    private let _next:() -> (E1, E2, E3)? 

    init<S1: Sequence, S2: Sequence, S3: Sequence>(_ s1: S1, _ s2: S2, _ s3: S3) where S1.Element == E1, S2.Element == E2, S3.Element == E3 { 
     var it1 = s1.makeIterator() 
     var it2 = s2.makeIterator() 
     var it3 = s3.makeIterator() 
     _next = { 
      guard let e1 = it1.next(), let e2 = it2.next(), let e3 = it3.next() else { return nil } 
      return (e1, e2, e3) 
     } 
    } 

    mutating func next() -> (E1, E2, E3)? { 
     return _next() 
    } 
} 

func zip3<S1: Sequence, S2: Sequence, S3: Sequence>(_ s1: S1, _ s2: S2, _ s3: S3) -> Zip3Sequence<S1.Element, S2.Element, S3.Element> { 
    return Zip3Sequence(s1, s2, s3) 
} 

let names = ["Joe", "Sarah", "Chad"] 
let ages = [18, 20, 22] 
let genders = ["Male", "Female", "Male"] 

for (name, age, gender) in zip3(names, ages, genders) { 
    print("Name: \(name), age: \(age), gender: \(gender)") 
} 

上面的代碼打印:

Name: Joe, age: 18, gender: Male 
Name: Sarah, age: 20, gender: Female 
Name: Chad, age: 22, gender: Male 
相關問題