सी # - दूसरे स्ट्रिंग से सबस्ट्रिंग की पहली घटना को हटाने का सबसे सरल तरीका


87

मुझे दूसरे स्ट्रिंग से स्ट्रिंग की पहली (और केवल पहली) घटना को हटाने की आवश्यकता है।

यहाँ एक उदाहरण स्ट्रिंग की जगह है "\\Iteration"। यह:

ProjectName \\ पुनरावृत्ति \\ Release1 \\ Iteration1

यह बन जाएगा:

ProjectName \\ Release1 \\ Iteration1

यहाँ कुछ कोड जो ऐसा करता है:

const string removeString = "\\Iteration";
int index = sourceString.IndexOf(removeString);
int length = removeString.Length;
String startOfString = sourceString.Substring(0, index);
String endOfString = sourceString.Substring(index + length);
String cleanPath = startOfString + endOfString;

बहुत कोड की तरह लगता है।

तो मेरा सवाल यह है कि क्या ऐसा करने के लिए एक क्लीनर / अधिक पठनीय / अधिक संक्षिप्त तरीका है?

जवाबों:


152
int index = sourceString.IndexOf(removeString);
string cleanPath = (index < 0)
    ? sourceString
    : sourceString.Remove(index, removeString.Length);

10
यह उत्तर गैर- ASCII वर्णों वाले तार के लिए टूट सकता है। उदाहरण के लिए, एन-यूएस संस्कृति के तहत, æऔर aeसमान माना जाता है। को निकालने का प्रयास paediaसे Encyclopædiaएक फेंक होगा ArgumentOutOfRangeExceptionजब से तुम 6 अक्षर दूर करने के लिए प्रयास कर रहे हैं, जब मिलान केवल सबस्ट्रिंग 5. शामिल
डगलस

6
हम इसे इस तरह संशोधित कर सकते हैं: sourceString.IndexOf(removeString, StringComparison.Ordinal)अपवाद से बचने के लिए।
बोरिस्लाव इवानोव

29
string myString = sourceString.Remove(sourceString.IndexOf(removeString),removeString.Length);

EDIT: @OregonGhost सही है। मैं स्वयं इस तरह की घटना की जांच करने के लिए सशर्त स्क्रिप्ट को तोड़ दूंगा, लेकिन मैं इस धारणा के तहत काम कर रहा था कि तार किसी न किसी आवश्यकता से एक-दूसरे से संबंधित हैं। यह संभव है कि व्यावसायिक-आवश्यक अपवाद हैंडलिंग नियमों से इस संभावना को पकड़ने की उम्मीद की जाती है। मैं स्वयं सशर्त जाँच करने के लिए अतिरिक्त लाइनों के एक जोड़े का उपयोग करूँगा और इसे कनिष्ठ डेवलपर्स के लिए थोड़ा और पठनीय बनाने के लिए जो इसे पूरी तरह से पढ़ने के लिए समय नहीं निकाल सकता है।


9
यदि स्ट्रैस्ट्रिंग सोर्सस्ट्रिंग में समाहित नहीं है तो यह क्रैश हो जाएगा।
ओरेगनगॉस्ट

26
sourceString.Replace(removeString, "");

18
String.Replace का कहना है कि यह " [r] एक नई स्ट्रिंग को बदल देता है जिसमें वर्तमान उदाहरण में एक निर्दिष्ट स्ट्रिंग के सभी आवृत्तियों को दूसरे निर्दिष्ट स्ट्रिंग के साथ बदल दिया जाता है "। ओपी पहली घटना को बदलना चाहता था ।
वाई हा ली

6
इसके अलावा, आपको अपना उत्तर थोड़ा स्पष्ट करना चाहिए क्योंकि कोड-केवल उत्तर स्वीकार्य नहीं हैं। अन्य उत्तरों पर एक नज़र डालें, और कुछ युक्तियों के लिए उनकी तुलना करें।
वाई हा ली

11

इसके लिए एक त्वरित टीडीडी टेस्ट लिखा

    [TestMethod]
    public void Test()
    {
        var input = @"ProjectName\Iteration\Release1\Iteration1";
        var pattern = @"\\Iteration";

        var rgx = new Regex(pattern);
        var result = rgx.Replace(input, "", 1);

        Assert.IsTrue(result.Equals(@"ProjectName\Release1\Iteration1"));
    }

rgx.Replace (इनपुट, "", 1); "", 1 समय के साथ पैटर्न से मेल खाने वाली किसी भी चीज़ के इनपुट में देखने के लिए कहते हैं।


2
जैसे आपने समस्या हल की। इस तरह की समस्या के लिए regex का उपयोग करते समय बस प्रदर्शन पर विचार करें।
थॉमस

7

आप मनोरंजन के लिए एक एक्सटेंशन विधि का उपयोग कर सकते हैं । आमतौर पर मैं स्ट्रिंग जैसे सामान्य प्रयोजन वर्ग के लिए विस्तार विधियों को संलग्न करने की सलाह नहीं देता, लेकिन जैसा मैंने कहा कि यह मजेदार है। मैंने @ ल्यूक के उत्तर को उधार लिया है क्योंकि पहिया का फिर से आविष्कार करने का कोई मतलब नहीं है।

[Test]
public void Should_remove_first_occurrance_of_string() {

    var source = "ProjectName\\Iteration\\Release1\\Iteration1";

    Assert.That(
        source.RemoveFirst("\\Iteration"),
        Is.EqualTo("ProjectName\\Release1\\Iteration1"));
}

public static class StringExtensions {
    public static string RemoveFirst(this string source, string remove) {
        int index = source.IndexOf(remove);
        return (index < 0)
            ? source
            : source.Remove(index, remove.Length);
    }
}

3
आप आमतौर पर स्ट्रिंग जैसे सामान्य उद्देश्य वर्ग के लिए एक्सटेंशन विधियों को संलग्न करने की अनुशंसा क्यों नहीं करते हैं? इस बारे में क्या स्पष्ट गिरावट हैं?
तीून कोइजमैन

1
इस तरह के सामान्य प्रयोजन वर्ग के लिए विशिष्ट उद्देश्य के लिए विस्तार विधि का निर्माण करना आसान है। उदाहरण के लिए, IsValidIBAN(this string input)इसे स्ट्रिंग पर रखना बहुत विशिष्ट होगा।
Squirrelkiller

3

यदि आप इस समस्या को हल करने के लिए एक सरल विधि चाहते हैं। (एक एक्सटेंशन के रूप में इस्तेमाल किया जा सकता है)

निचे देखो:

    public static string RemoveFirstInstanceOfString(this string value, string removeString)
    {
        int index = value.IndexOf(removeString, StringComparison.Ordinal);
        return index < 0 ? value : value.Remove(index, removeString.Length);
    }

उपयोग:

    string valueWithPipes = "| 1 | 2 | 3";
    string valueWithoutFirstpipe = valueWithPipes.RemoveFirstInstanceOfString("|");
    //Output, valueWithoutFirstpipe = " 1 | 2 | 3";

@ ल्यूक और @ माइक के उत्तर से प्रेरित और संशोधित।

संस्कृति सेटिंग्स के साथ समस्याओं को रोकने के लिए StringComparison.Ordinal को मत भूलना। https://www.jetbrains.com/help/resharper/2018.2/StringIndexOfIsCultureSpecific.1.html


2

मैं निश्चित रूप से सहमत हूं कि यह एक विस्तार विधि के लिए एकदम सही है, लेकिन मुझे लगता है कि इसमें थोड़ा सुधार किया जा सकता है।

public static string Remove(this string source, string remove,  int firstN)
    {
        if(firstN <= 0 || string.IsNullOrEmpty(source) || string.IsNullOrEmpty(remove))
        {
            return source;
        }
        int index = source.IndexOf(remove);
        return index < 0 ? source : source.Remove(index, remove.Length).Remove(remove, --firstN);
    }

यह थोड़ा सा पुनरावर्तन करता है जो हमेशा मजेदार होता है।

यहाँ एक सरल इकाई परीक्षण है:

   [TestMethod()]
    public void RemoveTwiceTest()
    {
        string source = "look up look up look it up";
        string remove = "look";
        int firstN = 2;
        string expected = " up  up look it up";
        string actual;
        actual = source.Remove(remove, firstN);
        Assert.AreEqual(expected, actual);

    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.