स्ट्रिंगर के साथ निर्मित स्ट्रिंग से अंतिम चरित्र को हटाने का सबसे अच्छा तरीका है


90

मेरे पास निम्नलिखित है

data.AppendFormat("{0},",dataToAppend);

इसके साथ समस्या यह है कि मैं इसे एक लूप में उपयोग कर रहा हूं और एक त्रिकोणीय अल्पविराम होगा। ट्रेलिंग कॉमा को हटाने का सबसे अच्छा तरीका क्या है?

क्या मुझे इसे स्ट्रिंग करने के लिए डेटा को स्ट्रिंग में बदलना होगा?


10
string.Join(",", yourCollection)? संपादित करें: उत्तर के रूप में जोड़ा गया।
व्लाद

1
क्या आपने stackoverflow.com/questions/5701163/… की कोशिश की ?
andreister

@ क्रिस: इस तरह से आप एक StringBuilder की जरूरत नहीं है।
व्लाद

शायद आप बाद में इसे हटाने के बजाय अल्पविराम को जोड़ने से बच सकते हैं। देखें: stackoverflow.com/questions/581448/... (जॉन स्कीट का जवाब)
पाओलो Falabella

@ व्लाद हाँ क्षमा करें, मैंने इसे गलत बताया है; मुझे लगा कि आप इसे अंतिम रूप से निर्मित स्ट्रिंग को बदलने के सुझाव के रूप में पेश कर रहे हैं, न कि उसके पाश के प्रतिस्थापन के रूप में। (मुझे लगा कि मैंने अपनी टिप्पणी समय में हटा दी, अनुमान नहीं!)
क्रिस सिनक्लेयर

जवाबों:


222

इस कमांड को करने का सबसे सरल और कुशल तरीका है:

data.Length--;

ऐसा करने से आप पॉइंटर (यानी पिछले इंडेक्स) को एक वर्ण वापस ले जाते हैं, लेकिन आप ऑब्जेक्ट की उत्परिवर्तन को नहीं बदलते हैं। वास्तव में, समाशोधन एक StringBuilderके Lengthरूप में अच्छी तरह से किया जाता है (लेकिन वास्तव में Clear()स्पष्टता के लिए विधि का उपयोग करें क्योंकि यह है कि इसका कार्यान्वयन कैसा दिखता है:)

data.Length = 0;

फिर से, क्योंकि यह आवंटन तालिका नहीं बदलता है। यह कहने की तरह सोचें, मैं अब इन बाइट्स को पहचानना नहीं चाहता। अब, यहां तक ​​कि फोन करते समय ToString(), यह अपने अतीत को कुछ भी नहीं पहचान Lengthसकता है, ठीक है, यह नहीं कर सकता। यह एक परिवर्तनशील वस्तु है जो आपको प्रदान करने की तुलना में अधिक स्थान आवंटित करता है, यह बस इस तरह से बनाया गया है।


2
पुन data.Length = 0;: यह वास्तव में क्या StringBuilder.Clearकरता है, इसलिए यह StringBuilder.Clearइरादा की स्पष्टता के लिए उपयोग करने के लिए बेहतर है ।
एरेन एर्सोन्मेज़

@ ErenErsönmez, उचित दोस्त, मुझे और अधिक स्पष्ट रूप से कहा जाना चाहिए कि क्या Clear()होता है, लेकिन मजेदार बात। यह विधि की पहली पंक्ति है Clear()। लेकिन, क्या आप जानते हैं कि इंटरफ़ेस वास्तव में जारी करता है return this;। अब वह चीज है जो मुझे मारती है। Length = 0आपके पास पहले से मौजूद संदर्भ को सेट करते हुए, अपने आप को क्यों लौटाएं?
माइक पेरेनॉड

12
मुझे लगता है कि यह "धाराप्रवाह" तरीके से उपयोग करने में सक्षम होने के लिए है। Appendखुद भी लौटता है।
एरेन एर्सोन्मेज़

43

महज प्रयोग करें

string.Join(",", yourCollection)

इस तरह से आपको StringBuilderऔर लूप की आवश्यकता नहीं है ।




Async केस के बारे में लंबा जोड़। 2019 तक, यह एक दुर्लभ सेटअप नहीं है जब डेटा अतुल्यकालिक रूप से आ रहे हैं।

यदि आपका डेटा async संग्रह में है, तो कोई string.Joinअधिभार नहीं है IAsyncEnumerable<T>। लेकिन मैन्युअल रूप से एक बनाना आसान है, इससे कोडstring.Join हैक करना :

public static class StringEx
{
    public static async Task<string> JoinAsync<T>(string separator, IAsyncEnumerable<T> seq)
    {
        if (seq == null)
            throw new ArgumentNullException(nameof(seq));

        await using (var en = seq.GetAsyncEnumerator())
        {
            if (!await en.MoveNextAsync())
                return string.Empty;

            string firstString = en.Current?.ToString();

            if (!await en.MoveNextAsync())
                return firstString ?? string.Empty;

            // Null separator and values are handled by the StringBuilder
            var sb = new StringBuilder(256);
            sb.Append(firstString);

            do
            {
                var currentValue = en.Current;
                sb.Append(separator);
                if (currentValue != null)
                    sb.Append(currentValue);
            }
            while (await en.MoveNextAsync());
            return sb.ToString();
        }
    }
}

यदि डेटा अतुल्यकालिक रूप से आ रहे हैं, लेकिन इंटरफ़ेस IAsyncEnumerable<T>समर्थित नहीं है (जैसे टिप्पणियों में उल्लेख किया गया है SqlDataReader), तो डेटा को इसमें लपेटना अपेक्षाकृत आसान है IAsyncEnumerable<T>:

async IAsyncEnumerable<(object first, object second, object product)> ExtractData(
        SqlDataReader reader)
{
    while (await reader.ReadAsync())
        yield return (reader[0], reader[1], reader[2]);
}

और इसका उपयोग करें:

Task<string> Stringify(SqlDataReader reader) =>
    StringEx.JoinAsync(
        ", ",
        ExtractData(reader).Select(x => $"{x.first} * {x.second} = {x.product}"));

उपयोग करने के लिए Select, आपको नगेट पैकेज का उपयोग करना होगा System.Interactive.Asyncयहां आप एक उदाहरण योग्य उदाहरण पा सकते हैं।


12
सबसे अच्छा उत्तर वह नहीं है जो समस्या को संबोधित करता है, बल्कि वह जो इसे रोकता है।
LastTribunal

1
@Seabizkit: बेशक! पूरा प्रश्न C # के बारे में है, वैसे।
व्लाद

1
@ मुझे लगता है कि, केवल दोहरी जाँच के रूप में मैं कच्चे परीक्षण की तरह सरल परीक्षण कर रहा हूँ और वे एक ही उत्पादन नहीं किया। string.Join(",", yourCollection)अभी भी ,अंत में है। इसलिए ऊपर यानी string.Join(",", yourCollection)अक्षम है और इसे अपने दम पर नहीं हटाता है।
सीबकिट

2
@ शेबेकट: बहुत अजीब है! क्या आप एक उदाहरण पोस्ट कर सकते हैं? मेरे कोड में यह पूरी तरह से काम करता है: ideone.com/aj8PWR
व्लाद

2
एक स्ट्रिंग बिल्डर का निर्माण करने के लिए लूप का उपयोग करने के वर्षों और फिर ट्रेलिंग कॉमा को हटा दें और मैं अभी इसका उपयोग कर सकता हूं। पारितोषिक के लिए धन्यवाद!
कावरमैन

11

लूप के बाद निम्नलिखित का उपयोग करें।

.TrimEnd(',')

या बस करने के लिए बदल जाते हैं

string commaSeparatedList = input.Aggregate((a, x) => a + ", " + x)

4
वह StringBuilder नहीं स्ट्रिंग का उपयोग कर रहा है। इसके अलावा यह काफी अप्रभावी है: पहले स्ट्रिंग में फिर ट्रिमिंग।
पायोत्र स्टैप

याstring.Join(",", input)
Tvde1

10

इस बारे में कैसा है..

string str = "The quick brown fox jumps over the lazy dog,";
StringBuilder sb = new StringBuilder(str);
sb.Remove(str.Length - 1, 1);

7

मैं स्ट्रिंगर की लंबाई में हेरफेर करना पसंद करता हूं:

data.Length = data.Length - 1;

4
क्यों नहीं बस data.Length--या --data.Length?
कोडिंग किया

मैं आमतौर पर data.Length-- का उपयोग करता हूं - लेकिन एक मामले में मुझे 2 पात्रों को वापस ले जाना पड़ा क्योंकि मैं जिस चरित्र को निकालना चाहता था, उसके बाद रिक्त मान। ट्रिम ने उस मामले में भी काम नहीं किया, इसलिए डेटा। काम किया।
कावरमैन

ट्रिम एक स्ट्रिंग का एक नया उदाहरण देता है, यह स्ट्रिंगर ऑब्जेक्ट की सामग्री को परिवर्तित नहीं करता है
bastos.sergio

@GoneCoding Visual Basic .NET समर्थन नहीं करता है --या ++ आप data.Length -= 1हालांकि उपयोग कर सकते हैं , या यह उत्तर भी काम करेगा।
जेसन एस

3

मेरा सुझाव है, आप अपना लूप अल्गोरिद्म बदलें:

  • आइटम जोड़ने के लिए अल्पविराम जोड़ें, लेकिन पहले से
  • एक बूलियन चर का उपयोग करें, जो झूठ के साथ शुरू होता है, पहले अल्पविराम को दबाएं
  • इस बूलियन चर को परीक्षण के बाद सही पर सेट करें

2
यह संभवतः सभी सुझावों में से सबसे कम कुशल है (और अधिक कोड की आवश्यकता है)।
कोडिंग गया

1
@ व्लाद का जवाब देखिए
Noctis

3

आपको string.Joinकॉमा सीमांकित स्ट्रिंग में आइटमों के संग्रह को चालू करने के लिए विधि का उपयोग करना चाहिए । यह सुनिश्चित करेगा कि कोई अग्रणी या अनुगामी अल्पविराम नहीं है, साथ ही यह सुनिश्चित करना है कि स्ट्रिंग का निर्माण कुशलतापूर्वक किया गया है (अनावश्यक मध्यवर्ती स्ट्रिंग्स के बिना)।


2

हां, लूप पूरा हो जाने पर इसे स्ट्रिंग में बदलें:

String str = data.ToString().TrimEnd(',');

3
यह काफी अप्रभावी है: स्ट्रिंग में पहली रूपांतरण फिर ट्रिमिंग।
पायोत्र स्टैप

2
@Garath यदि आपका मतलब "अक्षम" है, तो मैं असहमत नहीं होगा। लेकिन यह प्रभावी होगा
DonBoitnott

2

आपके पास दो विकल्प हैं। पहले एक बहुत आसान उपयोग Removeविधि है यह काफी प्रभावी है। दूसरा तरीका ToStringस्टार्ट इंडेक्स और एंड इंडेक्स ( MSDN प्रलेखन ) का उपयोग करना है



1

Join () विधि का उपयोग करने का सबसे सरल तरीका होगा:

public static void Trail()
{
    var list = new List<string> { "lala", "lulu", "lele" };
    var data = string.Join(",", list);
}

यदि आपको वास्तव में स्ट्रिंगब्यूलर की आवश्यकता है, तो लूप के बाद अंत कॉमा को ट्रिम करें:

data.ToString().TrimEnd(',');

4
data.ToString().TrimEnd(',');
अक्षम्य

1
इसके अलावा, आप StringBuilder वस्तु को String में बदलना नहीं चाह सकते क्योंकि इसकी कई लाइनें "," के साथ समाप्त हो सकती हैं
Fandango68
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.