स्ट्रिंग से सभी व्हाट्सएप को हटाने का कुशल तरीका?


358

मैं REST API कॉल कर रहा हूं और XML प्रतिक्रिया वापस प्राप्त कर रहा हूं। यह एक कार्यक्षेत्र नामों की सूची देता है, और मैं एक त्वरित IsExistingWorkspace()विधि लिख रहा हूं । चूंकि सभी कार्यस्थानों में बिना व्हाट्सएप के संक्रामक वर्ण होते हैं, इसलिए मैं यह पता लगाने का सबसे आसान तरीका मान रहा हूं कि क्या कोई विशेष कार्यक्षेत्र सूची में है, सभी व्हाट्सएप (न्यूलाइन सहित) को हटाने के लिए है और ऐसा करना (XML वेब से प्राप्त स्ट्रिंग है) निवेदन):

XML.Contains("<name>" + workspaceName + "</name>");

मुझे पता है कि यह केस-संवेदी है, और मैं उस पर भरोसा कर रहा हूं। मुझे एक स्ट्रिंग को कुशलतापूर्वक निकालने के लिए बस एक तरीके की आवश्यकता है। मुझे पता है कि RegEx और LINQ यह कर सकता है, लेकिन मैं अन्य विचारों के लिए खुला हूं। मैं ज्यादातर सिर्फ गति के बारे में चिंतित हूं।


6
रेक्स के साथ पार्सिंग एक्सएमएल लगभग उतना ही बुरा है जितना रीजेक्स के साथ HTML पार्स करना
dtb

3
@ जब होल्टरमैन; नीचे मेरा जवाब देखें, regexp सभी मामलों में सबसे तेज़ नहीं लगता है।
हेंक जे म्यूलकैंप

रेगेक्स बिल्कुल भी तेज नहीं लगता। मैंने एक स्ट्रिंग से व्हॉट्सएप को हटाने के लिए कई अलग-अलग तरीकों से परिणामों को संक्षेप में प्रस्तुत किया है। सारांश नीचे एक उत्तर में है - stackoverflow.com/a/37347881/582061
स्टियन स्टैंडहल

जवाबों:


616

यह सबसे तेज़ तरीका है, जिसका मुझे पता है, भले ही आपने कहा हो कि आप नियमित अभिव्यक्ति का उपयोग नहीं करना चाहते थे:

Regex.Replace(XML, @"\s+", "")

1
मैं एक नियमित अभिव्यक्ति का उपयोग कर सकता हूं, मुझे यकीन नहीं है कि यह सबसे तेज़ तरीका है।
कोरी ओगबर्न

1
मुझे पूरा यकीन है कि यह है। दृश्यों के पीछे बहुत कम से कम आपको हर चरित्र की जांच करनी होगी, और यह सिर्फ एक रैखिक खोज कर रहा है।
slandau

19
ऐसा नहीं होना चाहिए Regex.Replace(XML, @"\s+", "")?
Jan-Peter Vos

61
यदि आप एक से अधिक बार ऐसा करने की योजना बनाते हैं, तो एक रेगेक्स उदाहरण बनाएं और संग्रहीत करें। यह हर बार इसका निर्माण करने के ओवरहेड को बचाएगा, जो आपके विचार से अधिक महंगा है। private static readonly Regex sWhitespace = new Regex(@"\s+"); public static string ReplaceWhitespace(string input, string replacement) { return sWhitespace.Replace(input, replacement); }
ह्यपहुमन

10
RegEx के लिए नए लोगों के लिए और इस अभिव्यक्ति का मतलब क्या है के रूप में एक स्पष्टीकरण की तलाश में, \s"किसी भी व्हाट्सएप टोकन से मिलान करें", और +इसका अर्थ है "आगे बढ़ने वाले टोकन के एक या अधिक मिलान"। इसके अलावा RegExr , साथ रेगुलर एक्सप्रेशन से भाव लिख यदि आप प्रयोग करना चाहते हैं अभ्यास करने के लिए एक अच्छा वेबसाइट है।
जूनियर

181

मेरे पास regexp के बिना एक वैकल्पिक तरीका है, और यह बहुत अच्छा प्रदर्शन करता है। यह ब्रैंडन मोरेट के उत्तर पर एक निरंतरता है:

 public static string RemoveWhitespace(this string input)
 {
    return new string(input.ToCharArray()
        .Where(c => !Char.IsWhiteSpace(c))
        .ToArray());
 }

मैंने इसे एक साधारण इकाई परीक्षण में परखा:

[Test]
[TestCase("123 123 1adc \n 222", "1231231adc222")]
public void RemoveWhiteSpace1(string input, string expected)
{
    string s = null;
    for (int i = 0; i < 1000000; i++)
    {
        s = input.RemoveWhitespace();
    }
    Assert.AreEqual(expected, s);
}

[Test]
[TestCase("123 123 1adc \n 222", "1231231adc222")]
public void RemoveWhiteSpace2(string input, string expected)
{
    string s = null;
    for (int i = 0; i < 1000000; i++)
    {
        s = Regex.Replace(input, @"\s+", "");
    }
    Assert.AreEqual(expected, s);
}

1,000,000 विकल्पों के लिए पहला विकल्प (रेगेक्सपी के बिना) कम में चलता है तो दूसरा (मेरी मशीन पर 700 एमएस), और दूसरा 3.5 सेकंड के लिए।


40
.ToCharArray()इसकी आवश्यकता नही है; आप .Where()सीधे एक स्ट्रिंग पर उपयोग कर सकते हैं ।
प्रोग्रामफॉक्स

10
बस यहां ध्यान दें। रेगेक्स धीमा है ... छोटे तारों पर! यदि आप कहते हैं कि आपके पास अमेरिकी कर कानून (~ मिलियन शब्द?) पर वॉल्यूम का एक डिजीटल संस्करण है, तो कुछ मुट्ठी भर पुन: रेक्स राजा है, अब तक! यह नहीं कि क्या तेज है, लेकिन किस परिस्थिति में इसका उपयोग किया जाना चाहिए। आपने यहां केवल आधा समीकरण साबित किया। -1 जब तक आप परीक्षण के दूसरे छमाही को साबित नहीं करते हैं, ताकि जवाब कब और क्या उपयोग किया जाए, अधिक अंतर्दृष्टि प्रदान करता है।
पियोट्र कुला

17
@ppumkin उन्होंने व्हॉट्सएप के एक सिंगल पास को हटाने के लिए कहा। अन्य प्रसंस्करण के एकाधिक पुनरावृत्तियों नहीं। मैं इस सिंगल पास व्हाट्सएप को बेंचमार्किंग टेक्स्ट प्रोसेसिंग के बारे में विस्तारित पोस्ट में नहीं बनाने जा रहा हूं।
हेन्क जे म्युलकम्प

1
आपने कहा कि इस बार इसका उपयोग न करना पसंद है लेकिन ऐसा क्यों नहीं कहा।
पियोट्र कुला

2
@ProgramFOX, एक अलग प्रश्न में (इसे आसानी से नहीं पा सकते हैं) मैंने देखा कि कम से कम कुछ प्रश्नों में, स्ट्रिंग पर सीधे ToCharArrayउपयोग .Where()करने की तुलना में तेजी से उपयोग किया जाता है। यह IEnumerable<>प्रत्येक पुनरावृत्ति चरण में ओवरहेड के साथ कुछ करना है , और ToCharArrayबहुत कुशल (ब्लॉक-कॉपी) और संकलक सरणियों पर पुनरावृत्ति को अनुकूलित करता है। यह अंतर क्यों मौजूद है, कोई भी मुझे समझाने में सक्षम नहीं है, लेकिन इससे पहले कि आप हटा दें ToCharArray()
हाबिल

87

C # में स्ट्रिंग की जगह विधि का प्रयास करें।

XML.Replace(" ", string.Empty);

28
टैब या नई सूची नहीं निकालता है। यदि मैं एकाधिक हटाता हूं तो मैं स्ट्रिंग पर कई पास बना रहा हूं।
कोरी ओगबर्न

11
सभी व्हाट्सएप को हटाने के लिए डाउनवोट, जैसा कि स्कैंडाऊ और हेंक के उत्तर करते हैं।
मैट सच

@ मैट्सच यह सभी व्हाट्सएप को क्यों नहीं हटाता है?
ज़ाप्नोलोगिका

4
@Zapnologica यह केवल अंतरिक्ष पात्रों की जगह ले रहा है। ओपी ने नई कहानियों को बदलने के लिए कहा (जो कि "व्हाट्सएप" वर्ण हैं, भले ही वे एक अंतरिक्ष चरित्र नहीं हैं)।
मैट सच

75

मेरा समाधान स्प्लिट और जॉइन का उपयोग करना है और यह आश्चर्यजनक रूप से तेज है, वास्तव में यहां शीर्ष उत्तरों में सबसे तेज है।

str = string.Join("", str.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries));

नई लाइनों और टैब के साथ व्हॉट्सएप के साथ साधारण स्ट्रिंग पर 10,000 लूप के लिए समय

  • विभाजित / जुड़ना = 60 मिलीसेकंड
  • linq chararray = 94 मिलीसेकंड
  • रेगेक्स = 437 मिलीसेकंड

इसे अर्थ देने के लिए इसे विधि में लपेटकर इसे सुधारें, और जब हम इसमें हों तब इसे विस्तार विधि भी बनाएं ...

public static string RemoveWhitespace(this string str) {
    return string.Join("", str.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries));
}

3
मैं वास्तव में इस समाधान को पसंद करता हूं, मैं प्री-लाइनक्यू दिनों से एक समान उपयोग कर रहा हूं। मैं वास्तव में LINQs के प्रदर्शन से प्रभावित हूं, और रेगेक्स से कुछ हद तक हैरान हूं। शायद कोड उतना इष्टतम नहीं था जितना कि यह रेगेक्स के लिए हो सकता है (आपको उदाहरण के लिए रेगेक्स ऑब्जेक्ट को कैश करना होगा)। लेकिन समस्या की जड़ यह है कि डेटा की "गुणवत्ता" बहुत मायने रखती है। शायद लंबे समय तक तार के साथ रेगेक्स अन्य विकल्पों को बेहतर बना देगा। यह प्रदर्शन करने के लिए एक मजेदार बेंचमार्क होगा ... :-)
लाउडेनवियर

1
कैसे डिफ़ॉल्ट (स्ट्रिंग []) == सभी व्हाट्सएप पात्रों की एक सूची? मैं इसे काम करता देख रहा हूं, लेकिन मुझे समझ नहीं आ रहा है कि कैसे?
जेकू ड्रू

5
@kernowcode का अर्थ है कि आप के साथ 2 अतिभारों के बीच अस्पष्टता string[]और char[]? तुम सिर्फ तुम जैसे चाहते हैं जो एक निर्दिष्ट करने के लिए है: string.Join("", str.Split((string[])null, StringSplitOptions.RemoveEmptyEntries));। यह वास्तव defaultमें इस मामले में आपके कॉल करने के लिए क्या करता है क्योंकि यह भी लौटता है null: यह कंपाइलर को यह तय करने में मदद करता है कि किस अधिभार को चुनना है। इसलिए मेरी टिप्पणी क्योंकि आपकी टिप्पणी में बयान "विभाजन को एक वैध सरणी की आवश्यकता है और अशक्त नहीं होगा ..." गलत है। कोई बड़ी बात नहीं है, सिर्फ जेक ड्र्यू ने पूछा कि यह कैसे काम करता है, यह उल्लेख के लायक है। आपके उत्तर के लिए +1
फ्रैंक जे

6
शांत विचार ... लेकिन मैं इसे निम्नानुसार करूंगा:string.Concat("H \ne llo Wor ld".Split())
michaelkrisper

3
michaelkrisper समाधान बहुत पठनीय है। मैंने एक ही स्ट्रिंग के 10,000 पुनरावृत्तियों के लिए एक परीक्षण और 'स्प्लिट / जॉइन' (162 मिलीसेकंड) 'स्प्लिट / कॉन्कैट' (180 मिलीसेकंड) से बेहतर प्रदर्शन किया।
kernowcode

45

हेनक्स उत्तर पर निर्माण मैंने उनके उत्तर के साथ कुछ परीक्षण विधियां बनाई हैं और कुछ जोड़े, अधिक अनुकूलित, तरीके। मैंने पाया कि परिणाम इनपुट स्ट्रिंग के आकार के आधार पर भिन्न हैं। इसलिए, मैंने दो परिणाम सेटों के साथ परीक्षण किया है। सबसे तेज़ विधि में, लिंक किए गए स्रोत का और भी तेज़ तरीका है। लेकिन, चूंकि यह असुरक्षित है, इसलिए मैंने इसे छोड़ दिया है।

लंबे इनपुट स्ट्रिंग परिणाम:

  1. InPlaceCharArray: 2021 एमएस ( सूर्यास्त का जवाब ) - ( मूल स्रोत )
  2. स्ट्रिंग विभाजन तब सम्मिलित हों: 4277ms ( कर्नेलकोड का उत्तर )
  3. स्ट्रिंग रीडर: 6082 एमएस
  4. LINQ देशी char.IsWhitespace का उपयोग करते हुए: 7357 ms
  5. LINQ: 7746 एमएस ( हेंक का जवाब )
  6. फ़ोरलोप: 32320 मि
  7. RegexCompiled: 37157 एमएस
  8. रेगेक्स: 42940 एमएस

लघु इनपुट स्ट्रिंग परिणाम:

  1. InPlaceCharArray: 108 एमएस ( सूर्यास्त का जवाब ) - ( मूल स्रोत )
  2. स्ट्रिंग विभाजन तब सम्मिलित हों: 294 एमएस ( कर्नेलकोड का उत्तर )
  3. स्ट्रिंग रीडर: 327 एमएस
  4. फोरलोप: 343 मि
  5. LINQ देशी char.IsWhitespace का उपयोग करके: 624 ms
  6. LINQ: 645ms ( हेंक का जवाब )
  7. RegexCompiled: 1671 एमएस
  8. रेगेक्स: 2599 एमएस

कोड :

public class RemoveWhitespace
{
    public static string RemoveStringReader(string input)
    {
        var s = new StringBuilder(input.Length); // (input.Length);
        using (var reader = new StringReader(input))
        {
            int i = 0;
            char c;
            for (; i < input.Length; i++)
            {
                c = (char)reader.Read();
                if (!char.IsWhiteSpace(c))
                {
                    s.Append(c);
                }
            }
        }

        return s.ToString();
    }

    public static string RemoveLinqNativeCharIsWhitespace(string input)
    {
        return new string(input.ToCharArray()
            .Where(c => !char.IsWhiteSpace(c))
            .ToArray());
    }

    public static string RemoveLinq(string input)
    {
        return new string(input.ToCharArray()
            .Where(c => !Char.IsWhiteSpace(c))
            .ToArray());
    }

    public static string RemoveRegex(string input)
    {
        return Regex.Replace(input, @"\s+", "");
    }

    private static Regex compiled = new Regex(@"\s+", RegexOptions.Compiled);
    public static string RemoveRegexCompiled(string input)
    {
        return compiled.Replace(input, "");
    }

    public static string RemoveForLoop(string input)
    {
        for (int i = input.Length - 1; i >= 0; i--)
        {
            if (char.IsWhiteSpace(input[i]))
            {
                input = input.Remove(i, 1);
            }
        }
        return input;
    }

    public static string StringSplitThenJoin(this string str)
    {
        return string.Join("", str.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries));
    }

    public static string RemoveInPlaceCharArray(string input)
    {
        var len = input.Length;
        var src = input.ToCharArray();
        int dstIdx = 0;
        for (int i = 0; i < len; i++)
        {
            var ch = src[i];
            switch (ch)
            {
                case '\u0020':
                case '\u00A0':
                case '\u1680':
                case '\u2000':
                case '\u2001':
                case '\u2002':
                case '\u2003':
                case '\u2004':
                case '\u2005':
                case '\u2006':
                case '\u2007':
                case '\u2008':
                case '\u2009':
                case '\u200A':
                case '\u202F':
                case '\u205F':
                case '\u3000':
                case '\u2028':
                case '\u2029':
                case '\u0009':
                case '\u000A':
                case '\u000B':
                case '\u000C':
                case '\u000D':
                case '\u0085':
                    continue;
                default:
                    src[dstIdx++] = ch;
                    break;
            }
        }
        return new string(src, 0, dstIdx);
    }
}

टेस्ट :

[TestFixture]
public class Test
{
    // Short input
    //private const string input = "123 123 \t 1adc \n 222";
    //private const string expected = "1231231adc222";

    // Long input
    private const string input = "123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222123 123 \t 1adc \n 222";
    private const string expected = "1231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc2221231231adc222";

    private const int iterations = 1000000;

    [Test]
    public void RemoveInPlaceCharArray()
    {
        string s = null;
        var stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < iterations; i++)
        {
            s = RemoveWhitespace.RemoveInPlaceCharArray(input);
        }

        stopwatch.Stop();
        Console.WriteLine("InPlaceCharArray: " + stopwatch.ElapsedMilliseconds + " ms");
        Assert.AreEqual(expected, s);
    }

    [Test]
    public void RemoveStringReader()
    {
        string s = null;
        var stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < iterations; i++)
        {
            s = RemoveWhitespace.RemoveStringReader(input);
        }

        stopwatch.Stop();
        Console.WriteLine("String reader: " + stopwatch.ElapsedMilliseconds + " ms");
        Assert.AreEqual(expected, s);
    }

    [Test]
    public void RemoveLinqNativeCharIsWhitespace()
    {
        string s = null;
        var stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < iterations; i++)
        {
            s = RemoveWhitespace.RemoveLinqNativeCharIsWhitespace(input);
        }

        stopwatch.Stop();
        Console.WriteLine("LINQ using native char.IsWhitespace: " + stopwatch.ElapsedMilliseconds + " ms");
        Assert.AreEqual(expected, s);
    }

    [Test]
    public void RemoveLinq()
    {
        string s = null;
        var stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < iterations; i++)
        {
            s = RemoveWhitespace.RemoveLinq(input);
        }

        stopwatch.Stop();
        Console.WriteLine("LINQ: " + stopwatch.ElapsedMilliseconds + " ms");
        Assert.AreEqual(expected, s);
    }

    [Test]
    public void RemoveRegex()
    {
        string s = null;
        var stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < iterations; i++)
        {
            s = RemoveWhitespace.RemoveRegex(input);
        }

        stopwatch.Stop();
        Console.WriteLine("Regex: " + stopwatch.ElapsedMilliseconds + " ms");

        Assert.AreEqual(expected, s);
    }

    [Test]
    public void RemoveRegexCompiled()
    {
        string s = null;
        var stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < iterations; i++)
        {
            s = RemoveWhitespace.RemoveRegexCompiled(input);
        }

        stopwatch.Stop();
        Console.WriteLine("RegexCompiled: " + stopwatch.ElapsedMilliseconds + " ms");

        Assert.AreEqual(expected, s);
    }

    [Test]
    public void RemoveForLoop()
    {
        string s = null;
        var stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < iterations; i++)
        {
            s = RemoveWhitespace.RemoveForLoop(input);
        }

        stopwatch.Stop();
        Console.WriteLine("ForLoop: " + stopwatch.ElapsedMilliseconds + " ms");

        Assert.AreEqual(expected, s);
    }

    [TestMethod]
    public void StringSplitThenJoin()
    {
        string s = null;
        var stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < iterations; i++)
        {
            s = RemoveWhitespace.StringSplitThenJoin(input);
        }

        stopwatch.Stop();
        Console.WriteLine("StringSplitThenJoin: " + stopwatch.ElapsedMilliseconds + " ms");

        Assert.AreEqual(expected, s);
    }
}

संपादित करें : Kernowcode से एक अच्छा एक लाइनर का परीक्षण किया।


24

सिर्फ एक विकल्प क्योंकि यह काफी अच्छा लगता है :) - नोट: हेनक्स जवाब इनमें से सबसे तेज है।

input.ToCharArray()
 .Where(c => !Char.IsWhiteSpace(c))
 .Select(c => c.ToString())
 .Aggregate((a, b) => a + b);

परीक्षण 1,000,000 छोरों पर "This is a simple Test"

यह विधि = 1.74 सेकंड
रेगेक्स = 2.58 सेकंड
new String(हेनक्स) = 0.82


1
इसे क्यों ठुकरा दिया गया? यह पूरी तरह से स्वीकार्य है, आवश्यकताओं को पूरा करता है, RegEx विकल्प की तुलना में तेजी से काम करता है और बहुत पठनीय है?
ब्लूचिप्पी

4
क्योंकि यह बहुत छोटा लिखा जा सकता है: नया तार (इनपुट। कहीं भी (सी =>! चार। व्हाईटस्पेस (सी))। ToArray ());
बास स्मित

7
सच हो सकता है - लेकिन जवाब अभी भी खड़ा है, पठनीय है, रेगेक्स से तेज है और वांछित परिणाम पैदा करता है। अन्य जवाबों में से कई इस एक के बाद हैं ... इसलिए एक गिरावट का कोई मतलब नहीं है।
BlueChippy

2
क्या "0.82" के लिए एक इकाई है? या यह एक सापेक्ष माप (82%) है? क्या आप इसे और अधिक स्पष्ट करने के लिए अपने उत्तर को संपादित कर सकते हैं?
पीटर मोर्टेंसन

20

मुझे फेलिप मचाडो ( रिचर्ड रॉबर्टसन की मदद से ) कोडप्रोजेक्ट पर इस पर एक अच्छा लेखन मिला

उन्होंने दस अलग-अलग तरीकों का परीक्षण किया। यह एक सबसे तेज़ असुरक्षित संस्करण है ...

public static unsafe string TrimAllWithStringInplace(string str) {
    fixed (char* pfixed = str) {
        char* dst = pfixed;
        for (char* p = pfixed; *p != 0; p++)

            switch (*p) {

                case '\u0020': case '\u00A0': case '\u1680': case '\u2000': case '\u2001':

                case '\u2002': case '\u2003': case '\u2004': case '\u2005': case '\u2006':

                case '\u2007': case '\u2008': case '\u2009': case '\u200A': case '\u202F':

                case '\u205F': case '\u3000': case '\u2028': case '\u2029': case '\u0009':

                case '\u000A': case '\u000B': case '\u000C': case '\u000D': case '\u0085':
                    continue;

                default:
                    *dst++ = *p;
                    break;
            }

        return new string(pfixed, 0, (int)(dst - pfixed));
    }
}

और सबसे तेज़ सुरक्षित संस्करण ...

public static string TrimAllWithInplaceCharArray(string str) {

    var len = str.Length;
    var src = str.ToCharArray();
    int dstIdx = 0;

    for (int i = 0; i < len; i++) {
        var ch = src[i];

        switch (ch) {

            case '\u0020': case '\u00A0': case '\u1680': case '\u2000': case '\u2001':

            case '\u2002': case '\u2003': case '\u2004': case '\u2005': case '\u2006':

            case '\u2007': case '\u2008': case '\u2009': case '\u200A': case '\u202F':

            case '\u205F': case '\u3000': case '\u2028': case '\u2029': case '\u0009':

            case '\u000A': case '\u000B': case '\u000C': case '\u000D': case '\u0085':
                continue;

            default:
                src[dstIdx++] = ch;
                break;
        }
    }
    return new string(src, 0, dstIdx);
}

स्टियन स्टैंडहल द्वारा स्टैक ओवरफ्लो पर कुछ अच्छे स्वतंत्र बेंचमार्क भी हैं जो यह भी दिखाते हैं कि कैसे फेलिप का कार्य अगले सबसे तेज फ़ंक्शन की तुलना में लगभग 300% तेज है।


मैंने इसे C ++ में ट्रांसलेट करने की कोशिश की है लेकिन मैं थोड़ा अटक गया हूं। कोई भी विचार क्यों मेरा पोर्ट फेल हो रहा है? stackoverflow.com/questions/42135922/…
जॉन केज

2
मैं विरोध नहीं कर सकता। आपके द्वारा संदर्भित लेख के टिप्पणी अनुभाग में देखें। आप मुझे "बास्केटकेस सॉफ्टवेयर" के रूप में पाएंगे। उन्होंने और कुछ समय के लिए एक साथ इस पर काम किया। मैं इस बारे में पूरी तरह से भूल गया था जब यह समस्या फिर से आई। अच्छी यादों के लिए धन्यवाद। :)
रिचर्ड रॉबर्टसन

1
और क्या होगा यदि आप केवल अतिरिक्त WS निकालना चाहते हैं? इस stackoverflow.com/questions/17770202/… मॉड के बारे में क्या ?
टॉम

सबसे तेज़ थोड़ा धीमा है;; कंटेनर कंटेनर के रूप में स्ट्रिंग बेहतर है यहां (ऐप में 4:15 से 3:55 => 8.5% कम है, लेकिन जब बाएं स्ट्रिंग 3:30 => 21.4% कम और प्रोफाइलर शो लगभग 50% खर्च होता है यह विधि)। इसलिए वास्तविक लाइव स्ट्रिंग का उपयोग यहां (धीमी) सरणी रूपांतरण की तुलना में लगभग 40% अधिक तेज होना चाहिए।
टॉम

15

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

यदि आपको एक स्ट्रिंग से सभी सफेद रिक्त स्थान को पट्टी करने की आवश्यकता है, तो निम्नलिखित विधि सबसे तेजी से काम करती है जो यहां पोस्ट की गई है:

    public static string RemoveWhitespace(this string input)
    {
        int j = 0, inputlen = input.Length;
        char[] newarr = new char[inputlen];

        for (int i = 0; i < inputlen; ++i)
        {
            char tmp = input[i];

            if (!char.IsWhiteSpace(tmp))
            {
                newarr[j] = tmp;
                ++j;
            }
        }
        return new String(newarr, 0, j);
    }

मुझे आपके बेंचमार्किंग का विवरण जानने के लिए उत्सुक होना चाहिए - ऐसा नहीं है कि मुझे संदेह है, लेकिन मैं लिनक के साथ शामिल ओवरहेड के बारे में उत्सुक हूं। यह कितना बुरा था?
मार्क मेउर

मैंने सभी परीक्षणों को फिर से नहीं चलाया है, लेकिन मैं इसे बहुत याद रख सकता हूं: जो कुछ भी लिनेक को शामिल किया गया था, वह इसके बिना कुछ भी बहुत धीमा था। यदि स्ट्रिंग का उपयोग किया गया था, तो स्ट्रिंग / चार कार्यों और निर्माणकर्ताओं के सभी चतुर उपयोगों में कोई प्रतिशत अंतर नहीं था।
JHM

11

रेगेक्स ओवरकिल है; बस स्ट्रिंग पर विस्तार का उपयोग करें (धन्यवाद हेंक)। यह तुच्छ है और इसे ढांचे का हिस्सा होना चाहिए था। किसी भी तरह, यहाँ मेरा कार्यान्वयन है:

public static partial class Extension
{
    public static string RemoveWhiteSpace(this string self)
    {
        return new string(self.Where(c => !Char.IsWhiteSpace(c)).ToArray());
    }
}

यह मूल रूप से एक अनावश्यक उत्तर है (रेगेक्स ओवरकिल है, लेकिन दिए गए की तुलना में तेज समाधान है - और यह पहले से ही स्वीकार है?)
W1ll1amvl

आप एक स्ट्रिंग पर Linq एक्सटेंशन के तरीकों का उपयोग कैसे कर सकते हैं? यह पता नहीं लगा सकता कि मैं System.Linq
किसका

ठीक है ऐसा लगता है कि यह पीसीएल में उपलब्ध नहीं है, IEnumerable <char> Microsoft स्ट्रिंग कार्यान्वयन में सशर्त है ... और मैं Profile259 का उपयोग कर रहा हूं जो इस का समर्थन नहीं करता है :)
GGirard

4

यहाँ RegEx समाधान का एक सरल रैखिक विकल्प है। मुझे यकीन नहीं है कि जो तेज है; आपको इसे बेंचमार्क करना होगा।

static string RemoveWhitespace(string input)
{
    StringBuilder output = new StringBuilder(input.Length);

    for (int index = 0; index < input.Length; index++)
    {
        if (!Char.IsWhiteSpace(input, index))
        {
            output.Append(input[index]);
        }
    }
    return output.ToString();
}

3

मुझे रिक्त स्थान के साथ एक स्ट्रिंग में सफेद स्थान बदलने की आवश्यकता थी, लेकिन रिक्त स्थान की नकल नहीं। उदाहरण के लिए, मुझे निम्नलिखित जैसे कुछ बदलने की आवश्यकता है:

"a b   c\r\n d\t\t\t e"

सेवा

"a b c d e"

मैंने निम्नलिखित विधि का उपयोग किया

private static string RemoveWhiteSpace(string value)
{
    if (value == null) { return null; }
    var sb = new StringBuilder();

    var lastCharWs = false;
    foreach (var c in value)
    {
        if (char.IsWhiteSpace(c))
        {
            if (lastCharWs) { continue; }
            sb.Append(' ');
            lastCharWs = true;
        }
        else
        {
            sb.Append(c);
            lastCharWs = false;
        }
    }
    return sb.ToString();
}

2

मुझे लगता है कि आपकी XML प्रतिक्रिया इस तरह दिखती है:

var xml = @"<names>
                <name>
                    foo
                </name>
                <name>
                    bar
                </name>
            </names>";

XML को संसाधित करने का सबसे अच्छा तरीका एक XML पार्सर का उपयोग करना है, जैसे LINQ to XML :

var doc = XDocument.Parse(xml);

var containsFoo = doc.Root
                     .Elements("name")
                     .Any(e => ((string)e).Trim() == "foo");

एक बार जब मैं यह सत्यापित कर लेता हूं कि एक विशेष <नाम> टैग का उचित मूल्य है, तो मैं कर रहा हूं। दस्तावेज़ को पार्स करने से कुछ ओवरहेड नहीं होगा?
कोरी ओगबर्न

4
यकीन है, यह कुछ उपरि है। लेकिन इसके सही होने का फायदा है। रेगेक्स पर आधारित एक समाधान सही पाने के लिए बहुत अधिक कठिन है। यदि आप यह निर्धारित करते हैं कि एक LINQ to XML समाधान बहुत धीमा है, तो आप इसे हमेशा कुछ तेजी से बदल सकते हैं। लेकिन आपको सबसे कुशल कार्यान्वयन के लिए शिकार करने से बचना चाहिए इससे पहले कि आप जानते हैं कि सही एक बहुत धीमी है।
dtb

यह मेरे नियोक्ता के बैकेंड सर्वर में चलने वाला है। लाइटवेट वह है जिसकी मुझे तलाश है। मुझे कुछ ऐसा नहीं चाहिए जो "बस काम करता है" लेकिन इष्टतम है।
कोरी ओगबर्न

4
LINQ to XML सही तरीके से XML के साथ काम करने के सबसे हल्के तरीकों में से एक है। .NET
dtb

1

यहाँ अभी तक एक और प्रकार है:

public static string RemoveAllWhitespace(string aString)
{
  return String.Join(String.Empty, aString.Where(aChar => aChar !Char.IsWhiteSpace(aChar)));
}

अधिकांश अन्य समाधानों की तरह, मैंने विस्तृत बेंचमार्क परीक्षण नहीं किए हैं, लेकिन यह मेरे उद्देश्यों के लिए पर्याप्त रूप से काम करता है।


1

हम प्रयोग कर सकते हैं:

    public static string RemoveWhitespace(this string input)
    {
        if (input == null)
            return null;
        return new string(input.ToCharArray()
            .Where(c => !Char.IsWhiteSpace(c))
            .ToArray());
    }

यह लगभग बिल्कुल हेंक के उत्तर के समान है। फर्क सिर्फ इतना है कि आप जांच करते हैं null
कोरी ओगबर्न

हाँ, अशक्त के लिए जाँच
आयात

1
हो सकता है कि यह सिर्फ उनके जवाब पर एक टिप्पणी होनी चाहिए थी। मुझे खुशी है कि आप इसे ऊपर ले आए। मुझे नहीं पता था कि विस्तार के तरीकों को अशक्त वस्तुओं पर बुलाया जा सकता है।
कोरी ओगबर्न

0

मुझे सच होने के लिए अलग-अलग परिणाम मिले हैं। मैं एक जगह के साथ सभी व्हाट्सएप को बदलने की कोशिश कर रहा हूं और रेगेक्स बेहद धीमा था।

return( Regex::Replace( text, L"\s+", L" " ) );

मेरे लिए (C ++ क्ली में) सबसे अधिक आशातीत काम था:

String^ ReduceWhitespace( String^ text )
{
  String^ newText;
  bool    inWhitespace = false;
  Int32   posStart = 0;
  Int32   pos      = 0;
  for( pos = 0; pos < text->Length; ++pos )
  {
    wchar_t cc = text[pos];
    if( Char::IsWhiteSpace( cc ) )
    {
      if( !inWhitespace )
      {
        if( pos > posStart ) newText += text->Substring( posStart, pos - posStart );
        inWhitespace = true;
        newText += L' ';
      }
      posStart = pos + 1;
    }
    else
    {
      if( inWhitespace )
      {
        inWhitespace = false;
        posStart = pos;
      }
    }
  }

  if( pos > posStart ) newText += text->Substring( posStart, pos - posStart );

  return( newText );
}

मैंने प्रत्येक चरित्र को अलग से बदलकर पहले उपरोक्त दिनचर्या की कोशिश की, लेकिन गैर-अंतरिक्ष वर्गों के लिए सब्सट्रिंग करने के लिए स्विच करना पड़ा। 1,200,000 वर्ण स्ट्रिंग के लिए आवेदन करते समय:

  • उपरोक्त दिनचर्या 25 सेकंड में पूरी हो जाती है
  • उपरोक्त दिनचर्या + 95 सेकंड में अलग चरित्र प्रतिस्थापन
  • रेगेक्स 15 मिनट के बाद निरस्त हो गया।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.