2016-03-28 124 views
5

我希望能夠在Swift中使用map來修改我的對象數組,無需循環遍歷每個元素。在Swift中修改對象數組映射2.2(3.0)

這裏之前能夠做這樣的事情(更詳細here描述:

gnomes = gnomes.map { (var gnome: Gnome) -> Gnome in 
    gnome.age = 140 
    return gnome 
} 

感謝埃裏卡喪盾和其他新的提議都經歷了,現在我們擺脫C風格循環使用var內循環。

在我的情況下,我第一次得到一個警告,刪除var在隨後的錯誤我gnome是一個常數(自然)

我的問題是:我們如何修改map或新風格循環中的數組,以便爲​​Swift 3.0做好充分準備?

回答

13

如果你想保住你的語法,只需使用一個(可變)臨時變量

gnomes = gnomes.map { (gnome: Gnome) -> Gnome in 
    var mutableGnome = gnome 
    mutableGnome.age = 140 
    return mutableGnome 
} 
12

(以下如下,其中Gnome是引用類型的情況;一類 - 因爲你還沒有向我們展示你是如何定義Gnome對於那些Gnome爲值類型(結構),看情況@。 vadian:的回答)


var移除不會影響使用.map突變參考類型對象的陣列的可變成員。也就是說,你可以簡單地使用你的舊方法(然而,在.map閉包簽名中省略了var)。

class Gnome { 
    var age = 42 
} 

var gnomes = [Gnome(), Gnome(), Gnome()] 

gnomes = gnomes.map { 
    $0.age = 150 
    return $0 
} 

/* result */ 
gnomes.forEach { print($0.age) } // 3x 150 

但是,如果你只是想,而不是分配的.map結果到一個新的數組修改原始數組,.forEach可能比.map一個比較合適的選擇。

gnomes.forEach { $0.age = 140 } 

/* result */ 
gnomes.forEach { print($0.age) } // 3x 140 
+0

返回錯誤「$ 0 is immutable''。這是我的錯。我應該更加精確:(我使用的是結構而不是類,我敢打賭,默認情況下它們是不可變的 – kernelpanic

+0

@kernelpanic既然你沒有向我們展示'Gnome'類,我必須包括我自己的類。你確定你的類的'age'屬性是一個可變的屬性嗎?(以及你的gnome數組)?上面的工作在Swift 2.2和Xcode 7.3中適用。 – dfri

+0

@dfri我懷疑'Gnome'是一個結構 – vadian

1

考慮:

struct Gnome { 
    var age: Int = 0 
} 

var gnomes = Array(count: 5, repeatedValue: Gnome()) 

...有兩個不錯的選擇。首先是因爲@vadian所說的那樣:

gnomes = gnomes.map{ 
    var gnome = $0 
    gnome.age = 70 
    return gnome 
} 

而第二保持控制權「老化」 private,並在調用點簡化了映射:

struct Gnome { 
    private(set) var age: Int = 0 

    func aged(age: Int) -> Gnome { 
     var gnome = self 
     gnome.age = age 
     // any other ageing related changes 
     return gnome 
    } 
} 

gnomes = gnomes.map{ $0.aged(140) } 

當然,引用類型仍然有其放在編程中,這在這種情況下可能更適合。我們在這裏經歷的摩擦表明我們正在試圖將這些結構看作是物體。如果這是您需要的行爲,那麼您應該考慮將Gnome作爲class執行。