मैं किसी सरणी की सटीक डुप्लिकेट प्रतिलिपि कैसे बनाऊं?


100

मैं किसी सरणी का सटीक डुप्लिकेट कैसे बनाऊंगा?

मुझे स्विफ्ट में एक सरणी को डुप्लिकेट करने के बारे में जानकारी प्राप्त करने में मुश्किल समय हो रहा है।

मैंने प्रयोग करने की कोशिश की .copy()

var originalArray = [1, 2, 3, 4]
var duplicateArray = originalArray.copy()

5
क्यों न आप सीधे इस तरह मूल्य प्रदान करें:var duplicateArray = originalArray
धर्मेश खनेई

1
यह मेरे मामले में काम नहीं करता है। यह एक और ऑब्जेक्ट बनाता है जो केवल उसी ऐरे के लिए एक संदर्भ है और आप एक ही एरे को संदर्भित करते हुए 2 चर के साथ समाप्त होते हैं।
user1060500

जवाबों:


176

स्विफ्ट में एरे का पूरा मूल्य शब्दार्थ है, इसलिए किसी भी चीज की कोई आवश्यकता नहीं है।

var duplicateArray = originalArray आपको जो चाहिए वह यह है।


यदि आपके सरणी की सामग्री एक संदर्भ प्रकार है, तो हाँ, यह केवल आपकी वस्तुओं के लिए संकेत कॉपी करेगा। सामग्री की गहरी प्रतिलिपि बनाने के लिए, आप इसके बजाय mapप्रत्येक उदाहरण की एक प्रति का उपयोग और प्रदर्शन करेंगे। फ़ाउंडेशन वर्गों के लिए जो NSCopyingप्रोटोकॉल के अनुरूप हैं , आप copy()विधि का उपयोग कर सकते हैं :

let x = [NSMutableArray(), NSMutableArray(), NSMutableArray()]
let y = x
let z = x.map { $0.copy() }

x[0] === y[0]   // true
x[0] === z[0]   // false

ध्यान दें कि यहां ऐसे नुकसान हैं कि स्विफ्ट के मूल्य शब्दार्थ आपको उदाहरण के लिए रक्षा करने के लिए काम कर रहे हैं, क्योंकि NSArrayएक अपरिवर्तनीय सरणी का प्रतिनिधित्व करता है, इसकी copyविधि सिर्फ एक संदर्भ देती है, इसलिए ऊपर दिए गए परीक्षण अप्रत्याशित परिणाम प्राप्त करेंगे।


मैंने इस सरल कोड के साथ खेल के मैदान में कोशिश की var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }और मुझे यह आउटपुट मिला: ऐसा 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 नहीं लगता कि इसे कॉपी किया जा रहा है, क्या आप जानते हैं कि क्यों?
फिल नीडेर्टशाइडर

@PNGamingPower: x में पते शामिल हैं। y में उन पतों की प्रतियां हैं। यदि आप x [0] को बदल देते हैं, तो y [0] नहीं बदलेगा। (try x [0] = x [1], y [0] नहीं बदलेगा)। इस प्रकार, y x की एक गहरी प्रति है। लेकिन आपने केवल संकेतकर्ताओं की नकल की है, न कि वे जो इंगित कर रहे हैं।
ragnarius

@ श्रीगणेश तो मूल रूप से हमें परिभाषित करना है कि "कॉपी" का अर्थ क्या है, या तो पॉइंटर या मान की प्रतिलिपि बनाना। इसलिए यह संकेत के सरणी को कॉपी / डुप्लिकेट करने के लिए समाधान है, लेकिन आप मूल्यों की सरणी को कैसे दोहराते हैं? लक्ष्य होगा, x[0] == x[1]लेकिन x[0] === y[0]विफल होना चाहिए
फिल Niedertscheider

यह स्वीकृत उत्तर होना चाहिए, क्योंकि ऐरे का मान शब्दार्थ सरणी के "प्रतिलिपि" को अनावश्यक बनाता है।
स्कॉट एटेन

यह मेरे लिए काम नहीं करता है। यदि मैं उस विधि का पालन करता हूं, तो मुझे दो संदर्भ मिलते हैं जो वस्तुओं के एक ही सरणी की ओर इशारा करते हैं। यदि मैं सूची से कॉपी किए गए दोनों ऑब्जेक्ट संदर्भों में दिखाई देने वाली सूची से कोई आइटम निकालता हूं, लेकिन ऑब्जेक्ट को केवल संदर्भित किया गया था।
user1060500

28

नैट सही है। यदि आप आदिम सरणियों के साथ काम कर रहे हैं, तो आपको जो करना है वह डुप्लिकेट है।

पूर्णता के लिए, यदि आप एक NSArray ऑब्जेक्ट काम कर रहे थे, तो आप एक NSArray की पूरी कॉपी करने के लिए निम्न कार्य करेंगे:

var originalArray = [1, 2, 3, 4] as NSArray

var duplicateArray = NSArray(array:originalArray, copyItems: true)

यह भी खूब रही! धन्यवाद!
पैट्रिक

23

नैट के उत्तर के लिए एक तीसरा विकल्प है:

let z = x.map { $0 }  // different array with same objects

* आदर्श * एडिट यहां शुरू होता है

ऊपर अनिवार्य रूप से नीचे की तरह ही है और वास्तव में नीचे समानता ऑपरेटर का उपयोग करना बेहतर प्रदर्शन करेगा क्योंकि सरणी को कॉपी नहीं किया जाएगा जब तक कि इसे बदल नहीं दिया जाता है (यह डिजाइन द्वारा है)।

let z = x

यहां पढ़ें: https://developer.apple.com/swift/blog/?id=10

* आदर्श * एडिट यहां समाप्त होता है

इस सरणी को जोड़ने या हटाने से मूल सरणी प्रभावित नहीं होगी। हालाँकि, ऑब्जेक्ट के किसी भी गुण को बदलने से जो सरणी रखती है वह मूल सरणी में दिखाई देगा। क्योंकि सरणी में ऑब्जेक्ट कॉपी नहीं हैं (एरे होल्ड ऑब्जेक्ट्स को ग्रहण करते हैं, न कि आदिम संख्याएँ)।


यह प्रभाव डालता है, मैंने इसका परीक्षण किया है। दो ऐरे हैं, अगर 1 में यू बदला जाता है, तो दूसरा प्रभाव डालता है
गंदी नाइट

1
यह नहीं है, जब तक कि वस्तुओं के बजाय सरणी आदिम प्रकार धारण नहीं करती है। फिर यह उत्तर में बताए अनुसार प्रभावित करता है। एक साधारण परीक्षण मामला:var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
oyalhi

1
कृपया एक कस्टम वर्ग का उपयोग करके बेहतर उदाहरण के लिए बनाई गई इस जिस्ट को देखें
oyalhi

यदि आपका वर्ग समर्थन करता है NSCopying, तो एक सरणी को डुप्लिकेट करें:let z = x.map { $0.copy as! ClassX }
जॉन पैंग

यदि स्विफ्ट के बफ़रपॉइंटर्स का उपयोग किया जाता है, तो यह वह संस्करण है जिसे आपको इसकी सीधी प्रतिलिपि के रूप में उपयोग करना चाहिए। मूल या कॉपी किए गए सरणी में मान बदलने से पहले, स्विफ्ट मूल के मूल्यों को कॉपी में कॉपी कर देगा और फिर जारी रखेगा। यदि आप इसके बजाय पॉइंटर्स का उपयोग करते हैं, तो स्विफ्ट अब नहीं होगी या जब परिवर्तन होगा, इस प्रकार आप संभावित रूप से दोनों सरणियों को बदल सकते हैं।
जस्टिन गैंजर

16

सामान्य वस्तुओं के लिए जो कुछ किया जा सकता है वह एक प्रोटोकॉल को लागू करना है जो कॉपी करने का समर्थन करता है, और ऑब्जेक्ट क्लास को इस प्रोटोकॉल को इस तरह लागू करता है:

protocol Copying {
    init(original: Self)
}

extension Copying {
    func copy() -> Self {
        return Self.init(original: self)
    }
}

और फिर क्लोनिंग के लिए ऐरे एक्सटेंशन:

extension Array where Element: Copying {
    func clone() -> Array {
        var copiedArray = Array<Element>()
        for element in self {
            copiedArray.append(element.copy())
        }
        return copiedArray
    }
}

और यह बहुत अधिक है, कोड देखने के लिए और एक नमूना इस जिस्ट की जांच करें


इसने बहुत समय बचाया, धन्यवाद।
अभिजीत

उपवर्गों के लिए प्रोटोकॉल यह गारंटी नहीं दे सकता है कि उप-प्रकार के प्रकार के साथ आवक को लागू किया गया है। आप एक प्रतिलिपि प्रोटोकॉल की घोषणा कर रहे हैं जो आपके लिए प्रतिलिपि लागू करता है, लेकिन आप अभी भी क्लोन () को लागू कर रहे हैं, इसका कोई मतलब नहीं है।
बिरयानी

1
@ आईग्रोडिक कॉपी संग्रह में तत्वों के लिए है, और क्लोन पूरे संग्रह के लिए है, उपलब्ध है जब कॉपी अपने तत्वों के लिए लागू की जाती है। सही बात? इसके अलावा, संकलक सुनिश्चित करता है कि उपवर्ग उन प्रोटोकॉल का पालन करते हैं जिनकी उनके माता-पिता को आवश्यकता होती है।
जॉन्बेकर्स

@ जोबनबेकर ओह हाँ, अब मैं इसे देखता हूं। समझाने के लिए धन्यवाद।
बनिरियन

बहुत साफ कार्यान्वयन और object'sइनिट फ़ंक्शन में किसी भी पैरामीटर से गुजरने की अनावश्यक हलचल से बचा जाता है
सिल्वन डी ऐश

0

यदि आप किसी क्लास ऑब्जेक्ट की एक सरणी की वस्तुओं को कॉपी करना चाहते हैं। फिर आप NSCopying प्रोटोकॉल का उपयोग किए बिना नीचे दिए गए कोड का पालन कर सकते हैं, लेकिन आपके पास एक init तरीका होना चाहिए जो आपके ऑब्जेक्ट के लिए आवश्यक सभी मापदंडों को लेना चाहिए। यहाँ खेल के मैदान पर परीक्षण करने के लिए एक उदाहरण के लिए कोड है।

class ABC {
    
    var a = 0
    func myCopy() -> ABC {
        
        return ABC(value: self.a)
    }
    
    init(value: Int) {
        
        self.a = value
    }
}

var arrayA: [ABC] = [ABC(value: 1)]
var arrayB: [ABC] = arrayA.map { $0.myCopy() }

arrayB.first?.a = 2
print(arrayA.first?.a)//Prints 1
print(arrayB.first?.a)//Prints 2
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.