Изменение значения структуры в массиве
Я хочу хранить структуры внутри массива, получать доступ и изменять значения структуры в цикле for.
struct testing {
var value:Int
}
var test1 = testing(value: 6 )
test1.value = 2
// this works with no issue
var test2 = testing(value: 12 )
var testings = [ test1, test2 ]
for test in testings{
test.value = 3
// here I get the error:"Can not assign to 'value' in 'test'"
}
Если я изменил структуру на класс, она работает. Может кто-нибудь сказать мне, как я могу изменить значение структуры.
Ответы
Ответ 1
Кроме того, что говорит @MikeS, помните, что структуры являются типами значений. Итак, в цикле for
:
for test in testings {
a копировать элемента массива присваивается переменной test
. Любое изменение, которое вы делаете на нем, ограничено переменной test
, без каких-либо фактических изменений в элементах массива. Он работает для классов, потому что они являются ссылочными типами, поэтому ссылка, а не значение, копируется в переменную test
.
Правильный способ сделать это - использовать for
по индексу:
for index in 0..<testings.count {
testings[index].value = 15
}
в этом случае вы получаете доступ (и изменяете) фактический элемент структуры, а не его копию.
Ответ 2
Хорошо, я собираюсь обновить свой ответ для быстрой совместимости 3.
Когда вы программируете много, вам нужно изменить некоторые значения объектов, находящихся внутри коллекции. В этом примере у нас есть массив struct и при условии, что нам нужно изменить значение конкретного объекта. Это очень распространенная вещь в любой день разработки.
Вместо того, чтобы использовать индекс для определения того, какой объект должен быть изменен, я предпочитаю использовать условие if, которое IMHO является более распространенным.
import Foundation
struct MyStruct: CustomDebugStringConvertible {
var myValue:Int
var debugDescription: String {
return "struct is \(myValue)"
}
}
let struct1 = MyStruct(myValue: 1)
let struct2 = MyStruct(myValue: 2)
let structArray = [struct1, struct2]
let newStructArray = structArray.map({ (myStruct) -> MyStruct in
// You can check anything like:
if myStruct.myValue == 1 {
var modified = myStruct
modified.myValue = 400
return modified
} else {
return myStruct
}
})
debugPrint(newStructArray)
Обратите внимание на все варианты, этот способ разработки безопаснее.
Классы являются ссылочными типами, не нужно делать копию, чтобы изменить значение, как это происходит с structs. Используя тот же пример с классами:
class MyClass: CustomDebugStringConvertible {
var myValue:Int
init(myValue: Int){
self.myValue = myValue
}
var debugDescription: String {
return "class is \(myValue)"
}
}
let class1 = MyClass(myValue: 1)
let class2 = MyClass(myValue: 2)
let classArray = [class1, class2]
let newClassArray = classArray.map({ (myClass) -> MyClass in
// You can check anything like:
if myClass.myValue == 1 {
myClass.myValue = 400
}
return myClass
})
debugPrint(newClassArray)
Ответ 3
Это очень сложный ответ. Я думаю, Вам не следует делать это:
struct testing {
var value:Int
}
var test1 = testing(value: 6)
var test2 = testing(value: 12)
var ary = [UnsafeMutablePointer<testing>].convertFromArrayLiteral(&test1, &test2)
for p in ary {
p.memory.value = 3
}
if test1.value == test2.value {
println("value: \(test1.value)")
}
Для Xcode 6.1 инициализация массива будет
var ary = [UnsafeMutablePointer<testing>](arrayLiteral: &test1, &test2)
Ответ 4
Чтобы упростить работу с типами значений в массивах, вы можете использовать следующее расширение (Swift 3):
extension Array {
mutating func modifyForEach(_ body: (_ index: Index, _ element: inout Element) -> ()) {
for index in indices {
modifyElement(atIndex: index) { body(index, &$0) }
}
}
mutating func modifyElement(atIndex index: Index, _ modifyElement: (_ element: inout Element) -> ()) {
var element = self[index]
modifyElement(&element)
self[index] = element
}
}
Пример использования:
testings.modifyElement(atIndex: 0) { $0.value = 99 }
testings.modifyForEach { $1.value *= 2 }
testings.modifyForEach { $1.value = $0 }
Ответ 5
У тебя достаточно хороших ответов. Я просто рассмотрю вопрос с более общей точки зрения.
В качестве другого примера, чтобы лучше понять типы значений и что это означает, что они копируются:
struct Item {
var value:Int
}
var item1 = Item(value: 5)
func mutate (to value: Int){
item.value = value // cannot assign to property: 'item' is a 'let' constant
}
Это потому, что элемент копируется, когда он входит, он неизменен - для удобства.
Если бы вы сделали Item
типом класса, вы смогли изменить его значение.
var item2 = item1 // mutable COPY created
item2.value = 10
print(item2.value) // 10
print(item1.value) // 5
Ответ 6
Я попробовал ответить Антонио, который казался вполне логичным, но, к моему удивлению, это не сработало. Изучая это, я попробовал следующее:
struct testing {
var value:Int
}
var test1 = testing(value: 6 )
var test2 = testing(value: 12 )
var testings = [ test1, test2 ]
var test1b = testings[0]
test1b.value = 13
// I would assume this is same as test1, but it is not test1.value is still 6
// even trying
testings[0].value = 23
// still the value of test1 did not change.
// so I think the only way is to change the whole of test1
test1 = test1b
Ответ 7
Я закончил создание нового массива struct, как показано ниже.
func updateDefaultCreditCard(token: String) {
var updatedArray: [CreditCard] = []
for aCard in self.creditcards {
var card = aCard
card.isDefault = aCard.token == token
updatedArray.append(card)
}
self.creditcards = updatedArray
}