簡體   English   中英

Swift 4.2) 使用 for_in/forEach 改變結構數組與按索引訪問

[英]Swift 4.2) Mutate array of struct with for_in/forEach vs. access by index

我正在嘗試修改數組中的結構元素。 我發現您可以通過按索引訪問(迭代)結構來做到這一點,但如果您使用“for in”循環或 forEach{},則不能。

struct Person
{
  var age = 0
  var name = "James"
}

var personArray = [Person]()
personArray += [Person(), Person(), Person()]


personArray.forEach({$0.age = 10}) // error: "Cannot assign to property: '$0' is immutable"

for person in personArray { 
  person.age = 10 // error: "Cannot assign to property: 'person' is a 'let' constant"
}


for index in personArray.indices {
  personArray[index].age = 10 // Ok
}

有人可以解釋一下嗎?

正如其他答案中所述,您不能在for-in循環或.forEach方法中進行.forEach

您可以使用簡短而簡潔的最后一個公式:

for index in personArray.indices {
    personArray[index].age = 10
}

或者完全改變原始的personArray

personArray = personArray.map { person in 
    var person = person // parameter masking to allow local mutation
    person.age = 10
    return person
}

請注意,第二個選項似乎效率較低,因為它每次都創建一個新的Person實例,但 Swift 似乎針對這些情況進行了很好的優化。 時間分析器報告說,第二個選項的操作速度提高了近 2 倍,其中包含 1 000 000 Person的數組。

如果你真的想要.forEach方法的變異對應物,這里有一個獎勵,在MutableCollection上使用擴展:

extension MutableCollection {
    mutating func mutateEach(_ body: (inout Element) throws -> Void) rethrows {
        for index in self.indices {
            try body(&self[index])
        }
    }
}

這是一個相當於您的第一個公式的數組突變的包裝器,您可以按預期使用它:

personArray.mutateEach { $0.age = 10 }

在 Swift 中,結構體是一種類型。 在 for 或 foreach 循環中,person 項是一個值,如果它是可變的,您將只更改原始副本,而不是您想要的原始副本。

如果您真的想要對循環內結構的可更新引用,請添加 var 關鍵字,但請記住,您正在更新副本而不是原始副本。

for var person in personArray {
    person.age = 10 // updates a copy, not the original
}

相比之下, class 是一種引用類型,在循環中,每一項都是對原始項的引用。 更新此參考值現在會更新原始值。

將 Person 的定義更改為 class 而不是 struct ,它將按預期工作。 有關完整說明,請參閱https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM