Rust में iter बनाम into_iter: हुड के नीचे क्या छिपा है?

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

iter बनाम into_iter: Rust में इटरेशन के दिग्गजों की लड़ाई

\n\n

यदि आपने कभी Rust में किसी वेक्टर पर लूप लिखा है, तो आपने निश्चित रूप से तीन समान भाइयों का सामना किया होगा: iter(), into_iter() और iter_mut()। पहली नज़र में, ये सभी एक ही काम करते हैं - तत्वों के माध्यम से जाने की अनुमति देते हैं। लेकिन उनके बीच का अंतर जितना लगता है उससे कहीं अधिक गहरा है, और यह Rust के मूल में - स्वामित्व प्रणाली में छिपा है।

\n\n

कल्पना करें कि आप एक बरिस्ता हैं, और आपका संग्रह कॉफी बीन्स है। iter() आपको बीन्स को देखने, उन्हें सूंघने की अनुमति देता है, लेकिन छूने की नहीं। into_iter() तब होता है जब आप बीन्स लेते हैं, उन्हें पीसते हैं और एस्प्रेसो बनाते हैं, जिसके बाद बीन्स गायब हो जाते हैं। और iter_mut() - आप न केवल देख सकते हैं, बल्कि बैग में ही बीन्स को पीस सकते हैं, उनका आकार बदल सकते हैं।

\n\n

आज हम iter बनाम into_iter को उसी तरह समझेंगे जैसे Stack Overflow पर समझाया जाता है, लेकिन जीवंत उदाहरणों और हुड के नीचे गहराई से जाने के साथ। चलिए शुरू करते हैं!

\n\n

Rust में इटरेटर क्या है?

\n\n

इटरेटर एक ऐसी वस्तु है जो जानती है कि किसी संग्रह से क्रमिक रूप से तत्व कैसे प्राप्त करें। Rust में इटरेटर आलसी होते हैं: वे तब तक कुछ नहीं करते जब तक आप next() को कॉल नहीं करते। लेकिन मुख्य बात यह है कि इटरेशन की प्रत्येक विधि डेटा के स्वामित्व के साथ अलग-अलग व्यवहार करती है।

\n\n

यहाँ तीन मुख्य दृष्टिकोण हैं:

\n
    \n
  • iter() - तत्वों को उधार लेता है (स्वामित्व नहीं लेता)
  • \n
  • into_iter() - संग्रह को उपभोग करता है (स्वामित्व लेता है)
  • \n
  • iter_mut() - बदलने की क्षमता के साथ उधार लेता है
  • \n
\n\n

आइए कोड देखें। मान लीजिए हमारे पास नामों का एक वेक्टर है:

\n\n
let names = vec!["अन्ना".to_string(), "बोरिस".to_string(), "विक्टर".to_string()];
\n\n

उदाहरण 1: iter() - केवल देखना

\n\n
fn main() {\n    let names = vec!["अन्ना".to_string(), "बोरिस".to_string(), "विक्टर".to_string()];\n    \n    // iter() &String (संदर्भ) लौटाता है\n    for name in names.iter() {\n        println!("नमस्ते, {}!", name);\n    }\n    \n    // names अभी भी उपलब्ध है!\n    println!("वेक्टर जीवित है: {:?}", names);\n}
\n\n

ध्यान दें: लूप के बाद हम आराम से names का उपयोग करते हैं। क्यों? क्योंकि iter() ने प्रत्येक तत्व का संदर्भ लौटाया। स्वामित्व वेक्टर के पास रहा। यह सुरक्षित और पूर्वानुमानित है।

\n\n

उदाहरण 2: into_iter() - पुल जलाना

\n\n
fn main() {\n    let names = vec!["अन्ना".to_string(), "बोरिस".to_string(), "विक्टर".to_string()];\n    \n    // into_iter() String लौटाता है (स्वामित्व स्थानांतरित होता है)\n    for name in names.into_iter() {\n        println!("अलविदा, {}!", name);\n    }\n    \n    // त्रुटि! names अब मौजूद नहीं है\n    // println!("वेक्टर जीवित है: {:?}", names); // ❌ स्थानांतरित मान का उधार\n}
\n\n

यह है मुख्य अंतर। into_iter() संग्रह को उपभोग करता है। प्रत्येक तत्व लूप में स्थानांतरित हो जाता है, और मूल वेक्टर अमान्य हो जाता है। यदि आपको आगे उपयोग के लिए संग्रह को संरक्षित करने की आवश्यकता है - into_iter() आपका विकल्प नहीं है।

\n\n

उदाहरण 3: iter_mut() - बिना नष्ट किए बदलना

\n\n
fn main() {\n    let mut names = vec!["अन्ना".to_string(), "बोरिस".to_string(), "विक्टर".to_string()];\n    \n    // iter_mut() &mut String (परिवर्तनीय संदर्भ) लौटाता है\n    for name in names.iter_mut() {\n        name.push_str(" (अतिथि)");\n    }\n    \n    println!("बदला हुआ वेक्टर: {:?}", names);\n    // आउटपुट: ["अन्ना (अतिथि)", "बोरिस (अतिथि)", "विक्टर (अतिथि)"]\n}
\n\n

यहाँ हम तत्वों को उनके स्थान पर बदलते हैं, लेकिन स्वामित्व नहीं लेते। परिवर्तनों के लिए आदर्श।

\n\n

हुड के नीचे: प्रत्येक विधि क्या लौटाती है?

\n\n

iter बनाम into_iter को वास्तव में समझने के लिए, आइए मानक पुस्तकालय में देखें। वेक्टर Vec<T> के लिए:

\n\n
    \n
  • iter() std::slice::Iter<T> लौटाता है - यह Iterator<Item = &T> को लागू करता है

ब्लॉग

पुस्तक अनुशंसाएँ