2014-10-14 8 views
35

मैं एक सरणी के अंदर structs को स्टोर करना चाहता हूं, लूप के लिए संरचना के मानों को एक्सेस और बदलना चाहता हूं।बदलना एक सरणी में संरचना का मान

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'" 
} 

यदि मैं कक्षा में संरचना को बदलता हूं तो यह काम करता है। क्या कोई मुझे बता सकता है कि मैं संरचना के मूल्य को कैसे बदल सकता हूं।

+0

भी देखें [मूल्य प्रकार बनाम वर्ग प्रकार] (http://stackoverflow.com/a/41353620/5175709) रोब सही ढंग से कहते हैं: * यदि आप एक विधि है कि तब होता है के लिए एक पैरामीटर के रूप में एक मान प्रकार पारित किसी अन्य धागे पर कुछ, आप अनिवार्य रूप से उस मूल्य प्रकार की ** प्रति ** ** के साथ काम कर रहे हैं। यह विधि को पारित उस वस्तु की अखंडता सुनिश्चित करता है। * – Honey

उत्तर

46

@ माइकस द्वारा जो कहा गया उसके अलावा, याद रखें कि structs मूल्य प्रकार हैं। for पाश में तो:

for test in testings { 

एक सरणी तत्व की एक प्रतिलिपिtest चर को सौंपा गया है। आपके द्वारा किए गए किसी भी बदलाव को test परिवर्तनीय तक सीमित है, बिना सरणी तत्वों में कोई वास्तविक परिवर्तन किए। यह कक्षाओं के लिए काम करता है क्योंकि वे संदर्भ प्रकार हैं, इसलिए संदर्भ और मूल्य को test चर पर कॉपी किया गया है।

ऐसा करने के लिए उचित तरीके से सूचकांक द्वारा एक for का उपयोग करना है:

for index in 0..<testings.count { 
    testings[index].value = 15 
} 

इस मामले में आप तक पहुँचने (और संशोधित) कर रहे हैं वास्तविक struct तत्व और न इसकी एक प्रति।

+0

आश्चर्य की बात यह भी काम नहीं लगती है, और ऐसा लगता है कि यह एक प्रतिलिपि का मूल्य बदल रहा है। नीचे दिए गए मेरे उत्तर को देखें – reza23

+0

अपने उत्तर में मेरी टिप्पणी देखें - प्राप्त परिणाम अपेक्षित हैं क्योंकि आप अभी भी मूल्य प्रकार से निपट रहे हैं और संदर्भ नहीं – Antonio

+2

@ reza23 यह काम करता है। :) – nacho4d

0

मैंने एंटोनियो के जवाब की कोशिश की जो काफी तार्किक लग रहा था लेकिन मेरे आश्चर्य के लिए यह काम नहीं करता है। तलाश इस आगे मैं निम्नलिखित की कोशिश की:

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 
+6

आप भूल रहे हैं कि हर बार जब आप एक मूल्य प्रकार पास करते हैं, तो आप इसकी प्रतिलिपि पास करते हैं, संदर्भ नहीं। तो आपके द्वारा अपेक्षित परिणाम अपेक्षित हैं। 'test' को' test1' और 'test2' की ** प्रति ** ** के साथ प्रारंभ किया गया है। फिर, 'var test1b = testings [0]' में आप 'testings [0]' की एक नई प्रति बना रहे हैं, जो स्वयं 'test1' – Antonio

2

यह बहुत मुश्किल जवाब है। मुझे लगता है, आप इस की तरह नहीं करना चाहिए:

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) 
0

मैं पुनः 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 
} 
4

ठीक है, मैं तेजी से 3 संगतता के लिए अपना उत्तर अपडेट करने जा रहा हूं।

जब आप प्रोग्रामिंग कर रहे हैं तो आपको संग्रह के अंदर मौजूद वस्तुओं के कुछ मूल्यों को बदलने की आवश्यकता है। इस उदाहरण में हमारे पास संरचना की एक सरणी है और एक शर्त दी गई है जिसे हमें किसी विशिष्ट वस्तु के मान को बदलने की आवश्यकता है। किसी भी विकास दिवस में यह एक बहुत ही आम बात है।

यह निर्धारित करने के लिए कि कौन सा ऑब्जेक्ट संशोधित किया जाना है, एक इंडेक्स का उपयोग करने के बजाय मैं एक शर्त का उपयोग करना पसंद करता हूं, जो आईएमएचओ अधिक आम है।

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) 
+0

की एक प्रति है "अपना" नक्शा "शुद्ध नहीं कर रहा है? –

+0

@IanWarburton क्षमा करें, लेकिन मुझे यह समझ में नहीं आता है, "purer" से आपका क्या मतलब है? – LightMan

+0

मुझे लगता है कि यह कार्यात्मक प्रोग्रामिंग प्रतिमान के साथ अधिक अनुपालन का मतलब है। –

0

आपके पास पर्याप्त अच्छे उत्तर हैं। मैं सिर्फ एक सामान्य जेनेरिक कोण से सवाल से निपटूंगा।

एक और उदाहरण बेहतर मूल्य प्रकार समझने के लिए और क्या यह मतलब है कि वे कॉपी हो के रूप में:

struct Item { 
    var value:Int 
} 
var item1 = Item(value: 5) 

func testMutation (item: Item){ 
    item.value = 10 // cannot assign to property: 'item' is a 'let' constant 
} 

ऐसा इसलिए है क्योंकि आइटम कॉपी किया जाता है, जब यह आता है तो वह अपरिवर्तनीय है - एक सुविधा के रूप।


func anotherTest (item : Item){ 
    print(item.value) 
} 

anotherTest(item: item1) // 5 

कोई उत्परिवर्तन होता है तो कोई त्रुटि


var item2 = item1 // mutable copy created. 
item2.value = 10 
print(item2.value) // 10 
print(item1.value) // 5 
1

सरणियों आप निम्नलिखित एक्सटेंशन का उपयोग कर सकता है (स्विफ्ट 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 } 
संबंधित मुद्दे