Подтвердить что ты не робот

Изменение значения структуры в массиве

Я хочу хранить структуры внутри массива, получать доступ и изменять значения структуры в цикле 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'"
}

Если я изменил структуру на класс, она работает. Может кто-нибудь сказать мне, как я могу изменить значение структуры.

4b9b3361

Ответ 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
}