C # स्ट्रिंग में कई वर्ण बदलें


178

क्या तारों को बदलने का एक बेहतर तरीका है?

मुझे आश्चर्य है कि रिप्ले कैरेक्टर ऐरे या स्ट्रिंग ऐरे में नहीं लेता है। मुझे लगता है कि मैं अपना विस्तार लिख सकता था लेकिन मैं उत्सुक था कि क्या निम्न करने के लिए बेहतर तरीके से बनाया गया है? ध्यान दें अंतिम बदलें एक स्ट्रिंग है जो एक वर्ण नहीं है।

myString.Replace(';', '\n').Replace(',', '\n').Replace('\r', '\n').Replace('\t', '\n').Replace(' ', '\n').Replace("\n\n", "\n");

जवाबों:


206

आप एक नियमित अभिव्यक्ति की जगह ले सकते हैं।

s/[;,\t\r ]|[\n]{2}/\n/g
  • s/ शुरुआत में एक खोज का मतलब है
  • के बीच के अक्षर [और ]किसी भी क्रम में खोज करने के लिए वर्ण हैं
  • दूसरा /पाठ के लिए खोज और पाठ को प्रतिस्थापित करता है

अंग्रेजी में, यह पढ़ता है:

"के लिए खोज ;या ,या \tया \rया (स्थान) या ठीक दो अनुक्रमिक \nऔर साथ बदलें \n"

C # में, आप निम्न कार्य कर सकते हैं: (आयात करने के बाद System.Text.RegularExpressions)

Regex pattern = new Regex("[;,\t\r ]|[\n]{2}");
pattern.Replace(myString, "\n");

2
\tऔर \rमें शामिल हैं \s। तो आपका रेगेक्स के बराबर है [;,\s]
NullUserException

3
और \sवास्तव में इसके बराबर है [ \f\n\r\t\v]इसलिए आप कुछ सामानों को शामिल कर रहे हैं जो मूल प्रश्न में नहीं थे। Addtally, मूल प्रश्न पूछता है Replace("\n\n", "\n")जिसके लिए आपका regex हैंडल नहीं करता है।
NullUserException 2

11
कृपया विचार करें कि सरल प्रतिस्थापन परिचालनों के लिए, जो उपयोगकर्ता द्वारा कॉन्फ़िगर करने योग्य नहीं हैं, नियमित अभिव्यक्तियों का उपयोग करना इष्टतम नहीं है क्योंकि यह नियमित स्ट्रिंग संचालन की तुलना में बहुत धीमा है, पहले बेंचमार्क लेख के अनुसार जब मैंने "c # regex प्रदर्शन को प्रतिस्थापित किया" तो यह लगभग 13 है। समय धीमा।
भी

आह रेगेक्स, सत्ता के चित्रलिपि! एकमात्र मुद्दा जो मैं यहां देख सकता हूं वह नियमित अभिव्यक्तियों की मानवीय पठनीयता है; कई ने उन्हें समझने से इंकार कर दिया। मैंने हाल ही में एक कम जटिल विकल्प की तलाश करने वालों के लिए नीचे एक समाधान जोड़ा है।
s --unıɐ ɐ qɐp

तो अगर हम एक से अधिक वर्णों को एक से अधिक वर्णों के साथ बदलना चाहते हैं तो हम कैसे लिखें
हबीप ओउज

114

यदि आप विशेष रूप से चतुर महसूस कर रहे हैं और Regex का उपयोग नहीं करना चाहते हैं:

char[] separators = new char[]{' ',';',',','\r','\t','\n'};

string s = "this;is,\ra\t\n\n\ntest";
string[] temp = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);
s = String.Join("\n", temp);

आप थोड़े प्रयास के साथ इसे विस्तार विधि में लपेट सकते हैं।

संपादित करें: या बस 2 मिनट प्रतीक्षा करें और मैं इसे वैसे भी लिखना समाप्त कर दूंगा :)

public static class ExtensionMethods
{
   public static string Replace(this string s, char[] separators, string newVal)
   {
       string[] temp;

       temp = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);
       return String.Join( newVal, temp );
   }
}

और वोइला ...

char[] separators = new char[]{' ',';',',','\r','\t','\n'};
string s = "this;is,\ra\t\n\n\ntest";

s = s.Replace(separators, "\n");

बहुत स्मृति-अक्षम, विशेष रूप से बड़े तार के लिए।
MarcinJuraszek

@MarcinJuraszek Lol ... यह शायद पहली बार है जब मैंने कभी किसी को यह दावा करते सुना है कि अंतर्निहित स्ट्रिंग विधियाँ नियमित अभिव्यक्तियों की तुलना में कम स्मृति कुशल हैं।
पॉल वॉल्स

10
आप सही हे। इससे पहले कि मैं पोस्ट किया है मुझे मापा जाना चाहिए। मैं बेंचमार्क चलाता हूं और एक पंक्ति में Regex.Replaceकई string.Replaceकॉल्स की तुलना में 8 गुना धीमा हूं । और Split+ से 4 गुना धीमा JoinGist.github.com/MarcinJuraszek/c1437d925548561ba210a1c6ed144452
MarcinJuraszek

1
अच्छा समाधान! बस एक छोटा सा नशा। दुर्भाग्य से, यह काम नहीं करेगा यदि आप चाहते हैं कि पहला चरित्र (ओं) को भी बदल दिया जाए। आप उदाहरण स्ट्रिंग में 't' वर्ण को बदलना चाहते हैं। स्प्लिट मेथड सिर्फ 't' के पहले शब्द 'this' को छोड़ देगा क्योंकि यह एक EmptyEntry है। यदि आप RemoveEmptyEntries के बजाय StringSplitOptions.None का उपयोग करते हैं, तो स्प्लिट प्रविष्टि छोड़ देगा और Join विधि इसके बजाय विभाजक वर्ण जोड़ देगा। आशा है कि यह मदद करता है
पियरे

58

आप Linq के सकल कार्य का उपयोग कर सकते हैं:

string s = "the\nquick\tbrown\rdog,jumped;over the lazy fox.";
char[] chars = new char[] { ' ', ';', ',', '\r', '\t', '\n' };
string snew = chars.Aggregate(s, (c1, c2) => c1.Replace(c2, '\n'));

यहाँ विस्तार विधि है:

public static string ReplaceAll(this string seed, char[] chars, char replacementCharacter)
{
    return chars.Aggregate(seed, (str, cItem) => str.Replace(cItem, replacementCharacter));
}

एक्सटेंशन विधि उपयोग उदाहरण:

string snew = s.ReplaceAll(chars, '\n');

21

यह सबसे छोटा तरीका है:

myString = Regex.Replace(myString, @"[;,\t\r ]|[\n]{2}", "\n");

1
यह एक लाइनर भी मदद करता है जब आपको इनिशियलाइज़र में इसकी आवश्यकता होती है।
गनी ओजसन

8

ओह, प्रदर्शन हॉरर! जवाब थोड़ा पुराना है, लेकिन फिर भी ...

public static class StringUtils
{
    #region Private members

    [ThreadStatic]
    private static StringBuilder m_ReplaceSB;

    private static StringBuilder GetReplaceSB(int capacity)
    {
        var result = m_ReplaceSB;

        if (null == result)
        {
            result = new StringBuilder(capacity);
            m_ReplaceSB = result;
        }
        else
        {
            result.Clear();
            result.EnsureCapacity(capacity);
        }

        return result;
    }


    public static string ReplaceAny(this string s, char replaceWith, params char[] chars)
    {
        if (null == chars)
            return s;

        if (null == s)
            return null;

        StringBuilder sb = null;

        for (int i = 0, count = s.Length; i < count; i++)
        {
            var temp = s[i];
            var replace = false;

            for (int j = 0, cc = chars.Length; j < cc; j++)
                if (temp == chars[j])
                {
                    if (null == sb)
                    {
                        sb = GetReplaceSB(count);
                        if (i > 0)
                            sb.Append(s, 0, i);
                    }

                    replace = true;
                    break;
                }

            if (replace)
                sb.Append(replaceWith);
            else
                if (null != sb)
                    sb.Append(temp);
        }

        return null == sb ? s : sb.ToString();
    }
}

7

स्ट्रिंग्स बस अपरिवर्तनीय चार सरणियाँ हैं

आपको बस इसे परिवर्तनशील बनाने की आवश्यकता है:

  • या तो उपयोग करके StringBuilder
  • unsafeदुनिया में जाओ और संकेत के साथ खेलते हैं (हालांकि खतरनाक)

और वर्णों के सरणी के माध्यम से पुनरावृति करने का प्रयास करें। HashSetयहां ध्यान दें , क्योंकि यह लूप के अंदर वर्ण अनुक्रम को पार करने से बचता है। क्या आपको और भी तेज लुकअप की आवश्यकता है, आप (एक के आधार पर ) के HashSetलिए एक अनुकूलित लुकअप द्वारा प्रतिस्थापित कर सकते हैं ।chararray[256]

StringBuilder के साथ उदाहरण

public static void MultiReplace(this StringBuilder builder, 
    char[] toReplace, 
    char replacement)
{
    HashSet<char> set = new HashSet<char>(toReplace);
    for (int i = 0; i < builder.Length; ++i)
    {
        var currentCharacter = builder[i];
        if (set.Contains(currentCharacter))
        {
            builder[i] = replacement;
        }
    }
}

संपादित करें - अनुकूलित संस्करण

public static void MultiReplace(this StringBuilder builder, 
    char[] toReplace,
    char replacement)
{
    var set = new bool[256];
    foreach (var charToReplace in toReplace)
    {
        set[charToReplace] = true;
    }
    for (int i = 0; i < builder.Length; ++i)
    {
        var currentCharacter = builder[i];
        if (set[currentCharacter])
        {
            builder[i] = replacement;
        }
    }
}

तो आप इसे इस तरह से उपयोग करें:

var builder = new StringBuilder("my bad,url&slugs");
builder.MultiReplace(new []{' ', '&', ','}, '-');
var result = builder.ToString();

याद रखें कि स्ट्रिंग्स हैं wchar_t.net में, आप हर संभव पात्रों में से केवल एक सबसेट स्थान ले रही हैं (और आपको लगता है कि ... अनुकूलन करने के लिए 65536 bools की आवश्यकता होगी)
गोग

3

आप बस इन स्ट्रिंग एक्सटेंशन विधियों को भी लिख सकते हैं , और उन्हें अपने समाधान में कहीं रख सकते हैं:

using System.Text;

public static class StringExtensions
{
    public static string ReplaceAll(this string original, string toBeReplaced, string newValue)
    {
        if (string.IsNullOrEmpty(original) || string.IsNullOrEmpty(toBeReplaced)) return original;
        if (newValue == null) newValue = string.Empty;
        StringBuilder sb = new StringBuilder();
        foreach (char ch in original)
        {
            if (toBeReplaced.IndexOf(ch) < 0) sb.Append(ch);
            else sb.Append(newValue);
        }
        return sb.ToString();
    }

    public static string ReplaceAll(this string original, string[] toBeReplaced, string newValue)
    {
        if (string.IsNullOrEmpty(original) || toBeReplaced == null || toBeReplaced.Length <= 0) return original;
        if (newValue == null) newValue = string.Empty;
        foreach (string str in toBeReplaced)
            if (!string.IsNullOrEmpty(str))
                original = original.Replace(str, newValue);
        return original;
    }
}


उन्हें इस तरह से कॉल करें:

"ABCDE".ReplaceAll("ACE", "xy");

xyBxyDxy


और इस:

"ABCDEF".ReplaceAll(new string[] { "AB", "DE", "EF" }, "xy");

xyCxyF


2

RegEx.Replace का उपयोग करें, कुछ इस तरह से:

  string input = "This is   text with   far  too   much   " + 
                 "whitespace.";
  string pattern = "[;,]";
  string replacement = "\n";
  Regex rgx = new Regex(pattern);
  string result = rgx.Replace(input, replacement);

RegEx.Replace के लिए इस MSDN दस्तावेज़ पर अधिक जानकारी यहाँ दी गई है


1

प्रदर्शन-वार यह शायद सबसे अच्छा समाधान नहीं हो सकता है लेकिन यह काम करता है।

var str = "filename:with&bad$separators.txt";
char[] charArray = new char[] { '#', '%', '&', '{', '}', '\\', '<', '>', '*', '?', '/', ' ', '$', '!', '\'', '"', ':', '@' };
foreach (var singleChar in charArray)
{
   str = str.Replace(singleChar, '_');
}

1
string ToBeReplaceCharacters = @"~()@#$%&amp;+,'&quot;&lt;&gt;|;\/*?";
string fileName = "filename;with<bad:separators?";

foreach (var RepChar in ToBeReplaceCharacters)
{
    fileName = fileName.Replace(RepChar.ToString(), "");
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.