2011-03-10 21 views
12

मैं एक विशिष्ट चरित्र के द्वारा अलग कई क्षेत्रों, कुछ इस तरह से एक स्ट्रिंग के लिए असाइन परिणाम:सी #: स्प्लिट स्ट्रिंग और कई स्ट्रिंग चर

ए, बी, सी

मैं चाहता हूँ कॉमा पर स्ट्रिंग को विभाजित करने और प्रत्येक परिणामी फ़ील्ड को अपने स्ट्रिंग वेरिएबल को असाइन करने के लिए। पर्ल में मुझे लगता है कि सुंदर ढंग से कर सकते हैं इस तरह:

my ($varA, $varB, $varC) = split (/,/, $string); 

सरल और सबसे सुरुचिपूर्ण तरीका सी # में एक ही परिणाम प्राप्त करने के लिए क्या है?

मुझे पता है कि मैं एक सरणी में विभाजित कर सकते हैं:

string[] results = string.Split(','); 

लेकिन तब मैं अपने सूचकांक, उदा के माध्यम से खेतों का उपयोग करने के लिए होगा परिणाम [2]। पढ़ना मुश्किल है और त्रुटि-प्रवण - 3 बूथ 30 फ़ील्ड नहीं होने पर विचार करें। इसी कारण से मैं प्रत्येक फ़ील्ड मान को अपने नामित चर में रखना पसंद करता हूं।

+3

सी # के साथ इसे कैसे करें, इस पर कोई जवाब नहीं है, लेकिन एफ # आप जो भी चाहते हैं उससे काफी कुछ कर सकते हैं: 'चलो [| ए; ख; सी |] = "1,2,3" .प्लिट (',') ' –

+2

एफ # कमाल है। काश यह वाणिज्यिक सेटिंग्स में अधिक लोकप्रिय थे। –

उत्तर

8

मैं सहमत हूं। एक एडाप्टर वर्ग में विभाजित छिपाई जा रही है एक अच्छा दृष्टिकोण की तरह लगता है और अपने मंशा का नहीं बल्कि अच्छी तरह से:

public class MySplitter 
{ 
    public MySplitter(string split) 
    { 
     var results = string.Split(','); 
     NamedPartA = results[0]; 
     NamedpartB = results[1]; 
    } 

    public string NamedPartA { get; private set; } 
    public string NamedPartB { get; private set; } 
} 
+0

क्यों टुपल का उपयोग नहीं करते? – Linkgoron

+1

यदि मैं आपके उत्तर को सही ढंग से समझता हूं, तो इसे स्प्लिट के एक उपयोग प्रति परिदृश्य परिदृश्य की आवश्यकता होती है क्योंकि परिणामों की संख्या निश्चित रूप से नामों के साथ तय की जाती है। मैं नाम लचीला होना चाहता हूँ। –

+0

मैं कहूंगा कि इसे प्रति उदाहरण एक उदाहरण की आवश्यकता है जिसके लिए आप नाम रखना चाहते हैं। यह कोड का मामूली बिट है जो उपभोक्ता कोड को पढ़ने और समझने में आसान बनाता है। –

0

कोई सी # में रास्ते में बनाया गया है जैसे आप पर्ल में कर सकते हैं एक से अधिक काम करने के लिए; हालांकि, प्रत्येक चर में डेटा को सामान्य पथ के माध्यम से प्राप्त करने के लिए कई समाधान हैं।

+0

अच्छा, प्रत्येक चर में डेटा प्राप्त करने का सबसे शानदार तरीका क्या है? –

+0

मेरी राय में, रिच मेलटन (उपरोक्त) ने एक अच्छा समाधान पोस्ट किया - यह एक जटिल वस्तु के पीछे 'बकवास' (विभाजन) को सार तत्व बनाता है और उसके बाद परिणामी आउटपुट चर को गुणों में नामित करता है। – Tejs

1

मैं एक शब्दकोश की सिफारिश करता हूं।

List<string> names = new List<string>(){"varA","varB","varC"}; 
Dictionary<string, string> map = new Dictionary<string, string>(); 
string[] results = myLongString.Split(','); 
for (int i = 0; i < results.Length; i++) map.Add(names[i], results[i]); 
+0

यह मेरे लिए ओवरकिल जैसा दिखता है और पढ़ने के लिए बहुत आसान नहीं है (1 की बजाय 5 लाइनें)। –

7

आप टुपल्स (नेट 4 में जोड़ा गया) का उपयोग कर सकते हैं। Tuples in MSDN

यह:

public class MySplitter 
{ 
    public MySplitter(string split) 
    { 
     var results = split.Split(','); 
     NamedPartA = results[0]; 
     NamedpartB = results[1]; 
    } 

    public string NamedPartA { get; private set; } 
    public string NamedPartB { get; private set; } 
} 

कुछ इस तरह से हासिल किया जा सकता है:

public Tuple<string,string> SplitIntoVars(string toSplit) 
{ 
    string[] split = toSplit.Split(','); 
    return Tuple.Create(split[0],split[1]); 
} 

एक टपल के साथ आप उपयोग कर सकते हैं:

var x = SplitIntoVars(arr); 
// you can access the items like this: x.Item1 or x.Item2 (and x.Item3 etc.) 

तुम भी के लिए एक टपल बना सकते हैं आदि का उपयोग

इसके अलावा ... मुझे वास्तव में पैरामीटर पसंद नहीं हैं, इसलिए आप एक टुपल (और स्पष्ट रूप से, विभिन्न प्रकार के भी) का उपयोग करके कई मानों को वापस अनुकरण करते हैं। इस:

public void SplitIntoVariables(string input, out a, out b, out c) 
{ 
    string pieces[] = input.Split(','); 
    a = pieces[0]; 
    b = pieces[1]; 
    c = pieces[2]; 
} 

इस में बदल जाता है:

public Tuple<string,string,string> SplitIntoVariables(string[] input) 
    { 
     string pieces[] = input.Split(','); 
     return Tuple.Create(pieces[0],pieces[1],pieces[2]); 
    } 

अन्य (अधिक कल्पनाशील) विकल्प एक ExpandoObject (गतिशील) है कि अपने मूल्यों (ViewBag के लिए कुछ समान ASP.NET MVC में) रखती है बनाने जा सकता है

+1

दिलचस्प। पहले tuples के बारे में नहीं पता था। –

+0

टुपल का सुझाव नहीं देने का एक कारण यह तथ्य है कि परिणाम [0] tuple.Item1, Item2, आदि से ज्यादा स्पष्ट नहीं है .... ओपी ने स्पष्ट रूप से नामित मूल्यों की इच्छा जाहिर की है। –

+0

मुझे लगता है कि यह अभी भी सरणी से बेहतर है, क्योंकि यह वास्तव में इंडेक्स का उपयोग नहीं कर रहा है, और आप एफडब्लू में मौजूद संरचनाओं को फिर से नहीं बनाते हैं। किसी भी तरह से, मुझे लगता है कि सबसे अच्छा समाधान शायद एक समाधान शामिल करेगा जो वास्तविक समस्या के करीब है, और वर्तमान प्रश्न के रूप में कुछ सामान्य नहीं है।आईएमओ सबसे सुरुचिपूर्ण समाधान (यदि आप एक अच्छी ठोस वर्ग नहीं बना सकते हैं) कुछ गतिशील शब्दकोश (जैसे व्यूबैग) जैसा होगा। – Linkgoron

3

और जो कुछ लिंक पागलपन का विरोध नहीं कर सकता!

string names = "Joe,Bob,Lucy"; 
var myVars = names.Split(',').Select((x, index) => Tuple.Create(index,x)).ToDictionary(x => "var" + x.Item1, y => y.Item2); 
Debug.WriteLine(myVars["var0"]); 
+1

Sooo ... आपको स्ट्रिंग सरणी [इंडेक्स] की बजाय तारों का एक शब्दकोश [var + अनुक्रमणिका] मिला है? – Linkgoron

+3

वैसे यह पागल है ... – gt124

2

एक लाइन समाधान नहीं है।लेकिन, एक अतिरिक्त out पैरामीटर के साथ एक विस्तार विधि के बारे में कैसे?

public static IEnumerable<T> Unpack<T>(this IEnumerable<T> source, out T target) 
{ 
    target = source.First(); 
    return source.Skip(1); 
} 

उसके बाद, आप इस तरह विधि का उपयोग कर सकते हैं।

string values = "aaa,bbb,ccc"; 
string x, y, z; 
values.Split(',') 
    .Unpack(out x) 
    .Unpack(out y) 
    .Unpack(out z); 

ध्यान दें कि Unpack विधि दो बार अनुक्रम विश्लेषण करता है। इसलिए, मैं इसका उपयोग केवल तभी करूंगा जब IEnumerable ऑब्जेक्ट में डेटा दोहराने योग्य हो।

मुझे विधि के प्रदर्शन की जांच करने की परवाह नहीं थी क्योंकि मैंने सोचा था कि आम तौर पर हम एक बड़ी सरणी को अनपैक नहीं करेंगे।

बेशक, आप out के बजाय ref संशोधक का उपयोग कर सकते हैं, और उपयोग अलग होगा।

0

मैं हास्यास्पदता में जोड़ने का विरोध नहीं कर सका :) कृपया इस "समाधान" का उपयोग न करें, कम से कम नहीं।

static class StringExtensions 
{ 
    private static readonly Func<object, string, Action<object, object>> GetSetter = 
     (o1, n) => (o2, v) => o1.GetType().GetProperty(n).SetValue(o2, v, null); 

    public static T AssignFromCSV<T>(this string csv, T obj, string[] propertyNames) 
    { 
     var a = csv.Split(new[] {','}); 
     for (var i = 0 ; i < propertyNames.Length; i++) 
     { 
      GetSetter(obj, propertyNames[i])(obj, a[i]); 
     } 
     return obj ; 
    } 
} 

class TargetClass 
{ 
    public string A { get; set; } 

    public string B { get; set; } 

    public string C { get; set; } 
} 

उपयोग:

var target = "1,2,3".AssignFromCSV(new TargetClass(), new[] {"A", "B", "C"}) ; 
1

@pnvn अनपैक पैटर्न के साथ एक बहुत अच्छा विचार है, लेकिन यह गणनीय के अंत अतीत, एक भी पास में शुमार अधिक पुनरावृति चूक प्रदान करने के लिए सुधार किया जा सकता और एक अनुमानित तरीके से गणना के किसी भी प्रकार या आकार पर काम करते हैं।

यहां C# 7 out variables feature का उपयोग करके एक उदाहरण दिया गया है।

"A,B,C".Split(',') 
    .Unpack(out string varA) 
    .Unpack(out string varB); 

यह दो विस्तार के तरीकों, IEnumerable शुरू करने के लिए के लिए एक, प्रत्येक अनुवर्ती कॉल के लिए IEnumerator पर दूसरे की आवश्यकता है।

public static IEnumerator<T> Unpack<T>(this IEnumerable<T> source, out T item) 
{ 
    var enumerator = source.GetEnumerator(); 
    if (enumerator.MoveNext()) 
    { 
     item = enumerator.Current; 
     return enumerator; 
    } 
    item = default(T); 
    return null; 
} 

public static IEnumerator<T> Unpack<T>(this IEnumerator<T> enumerator, out T item) 
{ 
    if (enumerator != null && enumerator.MoveNext()) 
    { 
     item = enumerator.Current; 
     return enumerator; 
    }    
    item = default(T); 
    return null; 
} 
संबंधित मुद्दे