2015-09-02 8 views
10

मैं निम्नलिखित कोड का टुकड़ा के साथ एक HashMap में &str जोड़े का एक वेक्टर परिवर्तित करने के लिए कोशिश कर रहा हूँ:प्रकार मुद्दा इकट्ठा

use std::collections::HashMap; 

fn main() { 
    let pairs = vec!(("foo", "bar"), ("toto", "tata")); 
    let map: HashMap<&str, &str> = pairs.iter().collect(); 
    println!("{:?}", map); 
} 

हालांकि संकलन इस त्रुटि के साथ विफल:

<anon>:5:47: 5:56 error: the trait `core::iter::FromIterator<&(&str, &str)>` is not implemented for the type `std::collections::hash::map::HashMap<&str, &str>` [E0277] 
<anon>:5 let map: HashMap<&str, &str> = pairs.iter().collect(); 

हालांकि अगर collect() पर कॉल करने से पहले .cloned() जोड़ता है तो सब ठीक काम करता है:

यहां तक ​​कि अगर मैं त्रुटि संदेश को समझने मुझे समझ नहीं आता जहां प्रकार &(&str, &str) (जंग दस्तावेज में विधि हस्ताक्षर के अनुसार) और क्यों cloned() फिक्स बुला से आता है (वहाँ प्रकार HashMap<&str, &str> के लिए विशेषता FromIterator<&(&str, &str)> का कोई कार्यान्वयन है) इस समस्या।

उत्तर

12

प्रकार &(&str, &str) एक Vec रिटर्न पर क्या iter() से आता है:

fn iter(&self) -> Iter<T> 

जहां Iter<T> लागू Iterator<Item=&T>:

impl<'a, T> Iterator for Iter<'a, T> { 
    type Item = &'a T 
    ... 
} 

दूसरे शब्दों में, वेक्टर पर iter() वेक्टर में संदर्भ प्रस्तुत करने वाले एक पुनरावर्तक को लौटाता है।

cloned() समस्या का हल है क्योंकि यह एक इटरेटर एडाप्टर जो धर्मान्तरित Iterator<Item=&T>Iterator<Item=T>T के लिए अगर cloneable है। आप map(|v| v.clone()) के लिए एक आशुलिपि के रूप में यह के बारे में सोच सकते हैं:

let v1: Vec<i32> = vec![1, 2, 3, 4]; 
let v2: Vec<_> = v1.iter().cloned().collect(); 
let v3: Vec<_> = v1.iter().map(|v| v.clone()).collect(); 
assert_eq!(v2, v3); 

ऐसा होता है कि (&str, &str) cloneable है क्योंकि प्रत्येक टपल घटक भी cloneable है (सभी संदर्भों को कर रहे हैं), तो cloned() एक वस्तु जो Iterator<Item=(&str, &str)> लागू करता वापसी होगी - वास्तव में क्या collect()HashMap बनाने की आवश्यकता है।

वैकल्पिक रूप से, आप into_iter() का उपयोग Vec<T> से Iterator<Item=T> प्राप्त करने के लिए कर सकते हैं, लेकिन तब मूल सदिश भस्म हो जाएगा:

use std::collections::HashMap; 

fn main() { 
    let pairs = vec!(("foo", "bar"), ("toto", "tata")); 
    let map: HashMap<&str, &str> = pairs.into_iter().collect(); 
    println!("{:?}", map); 
} 
2

समस्या यह है कि संदर्भों की प्रतिलिपि बनाई जा सकती है, लेकिन tuples नहीं कर सकते हैं।

हालांकि, अगर आप जोड़े और आवश्यकता नहीं है, आप मूल्यों से पुनरावृति कर सकते हैं:

use std::collections::HashMap; 

fn main() { 
    let pairs = vec!(("foo", "bar"), ("toto", "tata")); 
    let map: HashMap<&'static str, &'static str> = pairs.into_iter().collect(); 
    println!("{:?}", map); 
} 
संबंधित मुद्दे