2015-10-19 7 views
18

को वीइसी कन्वर्ट मैं Vec<&str> को इस तरह से Vec<String> परिवर्तित कर सकते हैं: वीइसी <&str>

let mut items = Vec::<&str>::new(); 
for item in &another_items { 
    items.push(item); 
} 

मैं कल्पना वहाँ बेहतर विकल्प हैं?

उत्तर

1

यह एक collect उपयोग करता है:

let strs: Vec<&str> = another_items.iter().map(|s| s as &str).collect(); 
2
another_items.iter().map(|item| item.deref()).collect::<Vec<&str>>() 

deref() उपयोग करने के लिए आपके द्वारा उपयोग किए जोड़ना होगा use std::ops::Deref

20

वहाँ यह करने के लिए काफी कुछ तरीके, कुछ नुकसान कर रहे हैं, दूसरों को बस अधिक पठनीय हैं कुछ लोगों के लिए।

यह dereferences s (प्रकार &String की है) एक String "दाहिने हाथ की ओर संदर्भ" है, जो फिर एक str "दाहिने हाथ की ओर संदर्भ" के लिए Deref विशेषता के माध्यम से dereferenced है और फिर एक &str में वापस कर दिया है। यह ऐसा कुछ है जो आमतौर पर संकलक में देखा जाता है, और मैं इसे मूर्खतापूर्ण मानता हूं।

let v2: Vec<&str> = v.iter().map(|s| &**s).collect(); 

यहाँ Deref विशेषता के deref समारोह map कार्य करने के लिए दिया जाता है। यह बहुत साफ है लेकिन विशेषता के use की आवश्यकता है या पूरा पथ दे रहा है।

let v3: Vec<&str> = v.iter().map(std::ops::Deref::deref).collect(); 

यह हटाई गई है, यदि आप ऐसा नहीं करना चाहिए, क्योंकि यह |s| s: &str (बलात्कार वाक्य रचना) के साथ भविष्य में किया जा सकता है।

let v4: Vec<&str> = v.iter().map(|s| s as &str).collect(); 

यह (पूरे String में सिर्फ एक टुकड़ा) String के RangeFull टुकड़ा लेता है और यह करने के लिए एक संदर्भ लेता है। यह मेरी राय में बदसूरत है।

let v5: Vec<&str> = v.iter().map(|s| &s[..]).collect(); 

यह वह जगह है coercions का उपयोग करता है एक &str में एक &String कन्वर्ट करने के लिए। भविष्य में s: &str अभिव्यक्ति द्वारा भी प्रतिस्थापित किया जा सकता है।

let v6: Vec<&str> = v.iter().map(|s| { let s: &str = s; s }).collect(); 

निम्नलिखित (धन्यवाद @ huon-dbaupp) AsRef विशेषता है, जो पूरी तरह से अपने-अपने उधार प्रकार के स्वामित्व प्रकार से मैप करने के लिए मौजूद है उपयोग करता है। इसका उपयोग करने के दो तरीके हैं, और फिर, किसी भी संस्करण की सुंदरता पूरी तरह से व्यक्तिपरक है।

let v7: Vec<&str> = v.iter().map(|s| s.as_ref()).collect(); 

और

let v8: Vec<&str> = v.iter().map(AsRef::as_ref).collect(); 

मेरे लब्बोलुआब यह v8 समाधान का उपयोग के बाद से यह सबसे स्पष्ट रूप से व्यक्त करता है कि आप क्या चाहते है।

+2

स्पष्ट रूप से 'डेफ' (विशेष रूप से एक मुक्त फ़ंक्शन के रूप में) को कॉल करना काफी अजीब आईएमओ पढ़ता है, मुझे व्यक्तिगत रूप से 'v2' या 'v5' nicer मिलता है। (कोई भी 'as_ref', 'v.iter() का उपयोग कर सकता है। नक्शा (| s | s.as_ref()) ...' इस फ़ॉर्म के जेनेरिक रूपांतरणों के लिए सामान्य विधि है, उदाहरण के लिए 'std' में कई फ़ंक्शन 'पी: AsRef '।) – huon

+0

धन्यवाद, आप पूरी तरह से सही हैं। 'AsRef' यहां अधिक उपयुक्त है। मैंने पोस्ट अपडेट किया –

6

अन्य उत्तरों बस काम करते हैं।

fn my_func<T: AsRef<str>>(list: &[T]) { ... } 
बजाय

:

मैं बस का कहना है कि यदि आप एक Vec<&str> में Vec<String> कन्वर्ट करने के लिए कोशिश कर रहे हैं केवल यह एक समारोह Vec<&str> तर्क के रूप में लेने के लिए पास करना चाहते हैं, के रूप में समारोह हस्ताक्षर संशोधन पर विचार
fn my_func(list: &Vec<&str>) { ... } 

जैसा कि इस प्रश्न से इंगित किया गया है: Function taking both owned and non-owned string collections। इस तरह दोनों वैक्टर बस रूपांतरण की आवश्यकता के बिना काम करते हैं।

use std::iter::FromIterator; 

let v = Vec::from_iter(v.iter().map(String::as_str)); 

ध्यान दें कि String::as_str जंग 1.7 के बाद से स्थिर है:

संबंधित मुद्दे