कैपिटल लेटर्स से पहले रिक्त स्थान जोड़ें


193

स्ट्रिंग को देखते हुए "ThisStringHasNoSpacesButItDoesHaveCapicles" कैपिटल अक्षरों से पहले रिक्त स्थान जोड़ने का सबसे अच्छा तरीका क्या है। तो अंत स्ट्रिंग "यह स्ट्रिंग में कोई रिक्त स्थान नहीं है, लेकिन इसमें कैपिटल है"

यहाँ एक RegEx के साथ मेरा प्रयास है

System.Text.RegularExpressions.Regex.Replace(value, "[A-Z]", " $0")

2
क्या आपको अपने द्वारा लिए गए दृष्टिकोण के बारे में कोई विशेष शिकायत है? इससे हमें आपके तरीके पर सुधार करने में मदद मिल सकती है।
ब्लेयर कॉनराड

यदि रेगेक्स काम करता है, तो मैं उसके साथ रहना चाहूंगा। Regex को स्ट्रिंग हेरफेर के लिए ऑप्टिमाइज़ किया गया है।
माइकल मीडोज

मैं बस उत्सुक हूँ वहाँ एक बेहतर है या शायद एक भी दृष्टिकोण में बनाया है। मैं अन्य भाषाओं के साथ अन्य दृष्टिकोणों को देखने के लिए उत्सुक हूं।
बॉब

2
आपका कोड केवल इसलिए काम नहीं किया क्योंकि संशोधित स्ट्रिंग 'बदलें' फ़ंक्शन का रिटर्न मान है। इस कोड लाइन के साथ: 'System.Text.RegularExpressions.Regex.Replace (मान, "[AZ]", "$ 0") ट्रिम (); यह पूरी तरह से काम करेगा। (सिर्फ टिप्पणी करना क्योंकि मैं इस पद पर ठोकर खाई और किसी ने वास्तव में नहीं देखा, आपके कोड में क्या गड़बड़ी थी।)
मट्टू ४15५

Regex.Replace ("ThisStringHasNoSpacesButItDoesHaveCaplys", @ "\ B [AZ]", m => "" + m);
साहिब 13

जवाबों:


203

रेगेक्स ठीक काम करेगा (मैंने मार्टिन ब्राउन के जवाब भी दिए), लेकिन वे महंगे हैं (और व्यक्तिगत रूप से मुझे किसी भी तरह के वर्णों के प्रति निषेधात्मक रूप से मोटे तौर पर अधिक लंबा लगता है)

यह समारोह

string AddSpacesToSentence(string text, bool preserveAcronyms)
{
        if (string.IsNullOrWhiteSpace(text))
           return string.Empty;
        StringBuilder newText = new StringBuilder(text.Length * 2);
        newText.Append(text[0]);
        for (int i = 1; i < text.Length; i++)
        {
            if (char.IsUpper(text[i]))
                if ((text[i - 1] != ' ' && !char.IsUpper(text[i - 1])) ||
                    (preserveAcronyms && char.IsUpper(text[i - 1]) && 
                     i < text.Length - 1 && !char.IsUpper(text[i + 1])))
                    newText.Append(' ');
            newText.Append(text[i]);
        }
        return newText.ToString();
}

2,968,750 टिक्स में यह 100,000 बार करेगा, रेगेक्स 25,000,000 टिक (और रेगेक्स संकलित) के साथ ले जाएगा।

यह बेहतर है, दिए गए मूल्य के लिए बेहतर (यानी तेज) हालांकि इसे बनाए रखने के लिए अधिक कोड है। "बेहतर" अक्सर प्रतिस्पर्धी आवश्यकताओं का समझौता होता है।

उम्मीद है की यह मदद करेगा :)

अपडेट
यह एक अच्छा लंबा समय है क्योंकि मैंने इसे देखा है, और मुझे बस एहसास हुआ कि कोड बदलने के बाद से अपडेट नहीं किया गया है (यह केवल थोड़ा बदल गया है)।

'अब्ब्बbbbb' के साथ एक तार पर 100 बार (यानी 1,000 बाइट्स) दोहराया गया, 100,000 रूपांतरणों में से एक हाथ में कोडेड फंक्शन 4,517,177 टिक्स लेता है, और नीचे रेगेक्स 59,435,717 लेता है जिससे हैंड कोडित फंक्शन रन 7.6% समय में होता है। रेगेक्स।

अद्यतन 2 क्या इसे खाते में रखा जाएगा? यह अब होगा! अगर क़ानून का तर्क काफी अस्पष्ट है, जैसा कि आप इसे इस तक बढ़ाते हुए देख सकते हैं ...

if (char.IsUpper(text[i]))
    if (char.IsUpper(text[i - 1]))
        if (preserveAcronyms && i < text.Length - 1 && !char.IsUpper(text[i + 1]))
            newText.Append(' ');
        else ;
    else if (text[i - 1] != ' ')
        newText.Append(' ');

... बिल्कुल मदद नहीं करता है!

यहाँ मूल सरल विधि है जो परिवर्णी शब्द के बारे में चिंतित नहीं है

string AddSpacesToSentence(string text)
{
        if (string.IsNullOrWhiteSpace(text))
           return "";
        StringBuilder newText = new StringBuilder(text.Length * 2);
        newText.Append(text[0]);
        for (int i = 1; i < text.Length; i++)
        {
            if (char.IsUpper(text[i]) && text[i - 1] != ' ')
                newText.Append(' ');
            newText.Append(text[i]);
        }
        return newText.ToString();
}

8
अगर (char.IsUpper (पाठ [i]) && पाठ [i - 1]! = '') यदि आप ऊपर दिए गए कोड को फिर से चलाते हैं तो इसमें स्थान जुड़ते रहते हैं, इससे रिक्त स्थान बंद हो जाएंगे यदि राजधानी से पहले कोई स्थान है। पत्र।
पॉल टैलबोट

मुझे यकीन नहीं है कि मैंने सोचा था कि मैं पूछूंगा, क्या यह विधि समरूप है जो मार्टिन ब्राउन के जवाब में वर्णित है "DriveIsSCSICompatible" आदर्श रूप से "ड्राइव एससीएसआई संगत" बन जाएगा
Coops

यह 1 चरित्र बना दिया अगर नए बयान के साथ बयान के लिए अपने बयान की सामग्री की जगह, अगर मैं कुछ गलत कर रहा हूँ?
कूपर

1
Char.IsLetter (पाठ [i + 1]) के लिए एक चेक जोड़ने से विशेष वर्णों और अंकों (यानी ABC_DEF अभ्यस्त AB C_DEF के रूप में विभाजित हो जाते हैं) के साथ मदद करता है।
हेक्सानॉन

1
मुझे यकीन नहीं है कि जब बंद कर दिया जाता है तो समरूपी भाग सही होता है। मैं सिर्फ एक परीक्षण "ASentenceABC" "ASentence AB C" तक फैला है। "ए सेंटेंस एबी सी" होना चाहिए
टिम रटर

149

आपके समाधान में एक समस्या है कि यह पहले अक्षर T से पहले एक स्थान रखता है ताकि आप प्राप्त करें

" This String..." instead of "This String..."

निम्न केस लेटर के लिए इस रूप को प्राप्त करने के लिए इसे पहले भी देखें और फिर बीच में जगह डालें:

newValue = Regex.Replace(value, "([a-z])([A-Z])", "$1 $2");

1 संपादित करें:

यदि आप इसका उपयोग करते हैं, तो आप @"(\p{Ll})(\p{Lu})"उच्चारण पात्रों को भी चुन सकते हैं।

2 संपादित करें:

यदि आपके तार में समरूपता हो सकती है तो आप इसका उपयोग करना चाहते हैं:

newValue = Regex.Replace(value, @"((?<=\p{Ll})\p{Lu})|((?!\A)\p{Lu}(?>\p{Ll}))", " $0");

तो "DriveIsSCSICompatible" हो जाता है "ड्राइव SCSI संगत है"


3
क्या आप भी मूल RegEx और ट्रिम () परिणाम नहीं रख सकते हैं?
पांडावुड

3
@ पांडा आप कर सकते हैं, लेकिन इसके लिए एक और मेमोरी आवंटन और स्ट्रिंग कॉपी की आवश्यकता होगी। अगर प्रदर्शन एक चिंता का विषय है तो रेगेक्स किसी भी तरह से जाने का सबसे अच्छा तरीका नहीं है।
मार्टिन ब्राउन

क्या आप भी उपयोग कर सकते हैं "([^A-Z\\s])([A-Z])", यहां तक ​​कि परिवर्णी के साथ भी?
Ruben9922

82

प्रदर्शन का परीक्षण नहीं किया, लेकिन यहाँ लाइन के साथ एक पंक्ति में है:

var val = "ThisIsAStringToTest";
val = string.Concat(val.Select(x => Char.IsUpper(x) ? " " + x : x.ToString())).TrimStart(' ');

18

मुझे पता है कि यह एक पुराना है, लेकिन यह एक एक्सटेंशन है जिसका उपयोग मुझे तब करना पड़ता है जब मुझे ऐसा करने की आवश्यकता होती है:

public static class Extensions
{
    public static string ToSentence( this string Input )
    {
        return new string(Input.SelectMany((c, i) => i > 0 && char.IsUpper(c) ? new[] { ' ', c } : new[] { c }).ToArray());
    }
}

यह आपको उपयोग करने की अनुमति देगा MyCasedString.ToSentence()


मुझे यह एक विस्तार विधि के रूप में पसंद है, अगर आप TrimStart(' ')इसे जोड़ते हैं तो यह अग्रणी स्थान को हटा देगा।
user1069816

1
धन्यवाद @ user1069816 मैंने ओवरलोड का उपयोग करने के लिए एक्सटेंशन को बदल दिया है SelectManyजिसमें एक सूचकांक शामिल है, इस तरह यह पहले अक्षर और एक अतिरिक्त कॉल के अनावश्यक संभावित ओवरहेड से बचा जाता है TrimStart(' ')। रोब।
रोब हार्डी

9

मैंने बाइनरी वॉरियर के कोड के आधार पर एक सरल एक्सटेंशन विधि बनाने के लिए सेट किया है जो समरूपता को ठीक से संभाल लेगा, और पुन: प्रयोज्य है (पहले से ही शब्दों को स्थान नहीं देगा)। यहाँ मेरा परिणाम है।

public static string UnPascalCase(this string text)
{
    if (string.IsNullOrWhiteSpace(text))
        return "";
    var newText = new StringBuilder(text.Length * 2);
    newText.Append(text[0]);
    for (int i = 1; i < text.Length; i++)
    {
        var currentUpper = char.IsUpper(text[i]);
        var prevUpper = char.IsUpper(text[i - 1]);
        var nextUpper = (text.Length > i + 1) ? char.IsUpper(text[i + 1]) || char.IsWhiteSpace(text[i + 1]): prevUpper;
        var spaceExists = char.IsWhiteSpace(text[i - 1]);
        if (currentUpper && !spaceExists && (!nextUpper || !prevUpper))
                newText.Append(' ');
        newText.Append(text[i]);
    }
    return newText.ToString();
}

यहां फ़ंक्शन परीक्षण मामले हैं जो यह फ़ंक्शन गुजरता है। मैंने इस सूची में अधिकांश tchrist के सुझाए गए मामलों को जोड़ा। इनमें से जो तीन पास नहीं हैं (दो सिर्फ रोमन अंक हैं)

Assert.AreEqual("For You And I", "ForYouAndI".UnPascalCase());
Assert.AreEqual("For You And The FBI", "ForYouAndTheFBI".UnPascalCase());
Assert.AreEqual("A Man A Plan A Canal Panama", "AManAPlanACanalPanama".UnPascalCase());
Assert.AreEqual("DNS Server", "DNSServer".UnPascalCase());
Assert.AreEqual("For You And I", "For You And I".UnPascalCase());
Assert.AreEqual("Mount Mᶜ Kinley National Park", "MountMᶜKinleyNationalPark".UnPascalCase());
Assert.AreEqual("El Álamo Tejano", "ElÁlamoTejano".UnPascalCase());
Assert.AreEqual("The Ævar Arnfjörð Bjarmason", "TheÆvarArnfjörðBjarmason".UnPascalCase());
Assert.AreEqual("Il Caffè Macchiato", "IlCaffèMacchiato".UnPascalCase());
//Assert.AreEqual("Mister Dženan Ljubović", "MisterDženanLjubović".UnPascalCase());
//Assert.AreEqual("Ole King Henry Ⅷ", "OleKingHenryⅧ".UnPascalCase());
//Assert.AreEqual("Carlos Ⅴº El Emperador", "CarlosⅤºElEmperador".UnPascalCase());
Assert.AreEqual("For You And The FBI", "For You And The FBI".UnPascalCase());
Assert.AreEqual("A Man A Plan A Canal Panama", "A Man A Plan A Canal Panama".UnPascalCase());
Assert.AreEqual("DNS Server", "DNS Server".UnPascalCase());
Assert.AreEqual("Mount Mᶜ Kinley National Park", "Mount Mᶜ Kinley National Park".UnPascalCase());

यहां पोस्ट किए गए अन्य समाधान के समान, यह स्ट्रिंग "रेग्युलर" के साथ विफल हो जाता है। यह "रेगुलर ओ टीएस"
पाटे गुटी

8

यूनिकोड में आपका स्वागत है

ये सभी समाधान आधुनिक पाठ के लिए अनिवार्य रूप से गलत हैं। आपको कुछ ऐसा उपयोग करने की आवश्यकता है जो मामले को समझता है। चूंकि बॉब ने अन्य भाषाओं के लिए कहा, मैं पर्ल के लिए एक जोड़ी दूंगा।

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

Testing TheLoneRanger
               Worst:    The_Lone_Ranger
               Ok:       The_Lone_Ranger
               Better:   The_Lone_Ranger
               Best:     The_Lone_Ranger
Testing MountMKinleyNationalPark
     [WRONG]   Worst:    Mount_MKinley_National_Park
     [WRONG]   Ok:       Mount_MKinley_National_Park
     [WRONG]   Better:   Mount_MKinley_National_Park
               Best:     Mount_M_Kinley_National_Park
Testing ElÁlamoTejano
     [WRONG]   Worst:    ElÁlamo_Tejano
               Ok:       El_Álamo_Tejano
               Better:   El_Álamo_Tejano
               Best:     El_Álamo_Tejano
Testing TheÆvarArnfjörðBjarmason
     [WRONG]   Worst:    TheÆvar_ArnfjörðBjarmason
               Ok:       The_Ævar_Arnfjörð_Bjarmason
               Better:   The_Ævar_Arnfjörð_Bjarmason
               Best:     The_Ævar_Arnfjörð_Bjarmason
Testing IlCaffèMacchiato
     [WRONG]   Worst:    Il_CaffèMacchiato
               Ok:       Il_Caffè_Macchiato
               Better:   Il_Caffè_Macchiato
               Best:     Il_Caffè_Macchiato
Testing MisterDženanLjubović
     [WRONG]   Worst:    MisterDženanLjubović
     [WRONG]   Ok:       MisterDženanLjubović
               Better:   Mister_Dženan_Ljubović
               Best:     Mister_Dženan_Ljubović
Testing OleKingHenry
     [WRONG]   Worst:    Ole_King_Henry
     [WRONG]   Ok:       Ole_King_Henry
     [WRONG]   Better:   Ole_King_Henry
               Best:     Ole_King_Henry_
Testing CarlosⅤºElEmperador
     [WRONG]   Worst:    CarlosⅤºEl_Emperador
     [WRONG]   Ok:       CarlosⅤº_El_Emperador
     [WRONG]   Better:   CarlosⅤº_El_Emperador
               Best:     Carlos_Ⅴº_El_Emperador

BTW, यहाँ लगभग हर किसी ने पहला रास्ता चुना है, एक "सबसे खराब" चिह्नित है। कुछ ने दूसरा रास्ता चुना है, "ओके" को चिह्नित किया है। लेकिन मुझसे पहले किसी और ने आपको "बेहतर" या "सर्वश्रेष्ठ" दृष्टिकोण करने का तरीका नहीं दिखाया।

यहां इसकी चार विधियों के साथ परीक्षण कार्यक्रम है:

#!/usr/bin/env perl
use utf8;
use strict;
use warnings;

# First I'll prove these are fine variable names:
my (
    $TheLoneRanger              ,
    $MountMKinleyNationalPark  ,
    $ElÁlamoTejano              ,
    $TheÆvarArnfjörðBjarmason   ,
    $IlCaffèMacchiato           ,
    $MisterDženanLjubović         ,
    $OleKingHenry              ,
    $CarlosⅤºElEmperador        ,
);

# Now I'll load up some string with those values in them:
my @strings = qw{
    TheLoneRanger
    MountMKinleyNationalPark
    ElÁlamoTejano
    TheÆvarArnfjörðBjarmason
    IlCaffèMacchiato
    MisterDženanLjubović
    OleKingHenry
    CarlosⅤºElEmperador
};

my($new, $best, $ok);
my $mask = "  %10s   %-8s  %s\n";

for my $old (@strings) {
    print "Testing $old\n";
    ($best = $old) =~ s/(?<=\p{Lowercase})(?=[\p{Uppercase}\p{Lt}])/_/g;

    ($new = $old) =~ s/(?<=[a-z])(?=[A-Z])/_/g;
    $ok = ($new ne $best) && "[WRONG]";
    printf $mask, $ok, "Worst:", $new;

    ($new = $old) =~ s/(?<=\p{Ll})(?=\p{Lu})/_/g;
    $ok = ($new ne $best) && "[WRONG]";
    printf $mask, $ok, "Ok:", $new;

    ($new = $old) =~ s/(?<=\p{Ll})(?=[\p{Lu}\p{Lt}])/_/g;
    $ok = ($new ne $best) && "[WRONG]";
    printf $mask, $ok, "Better:", $new;

    ($new = $old) =~ s/(?<=\p{Lowercase})(?=[\p{Uppercase}\p{Lt}])/_/g;
    $ok = ($new ne $best) && "[WRONG]";
    printf $mask, $ok, "Best:", $new;
}

जब आप इस डेटासेट पर "सर्वश्रेष्ठ" के समान स्कोर कर सकते हैं, तो आपको पता चल जाएगा कि आपने इसे सही तरीके से किया है। तब तक, आपने नहीं किया। यहां किसी और ने "ओके" से बेहतर नहीं किया है, और अधिकांश ने "वर्स्ट" किया है। मैं सही the कोड किसी को देखने के लिए उत्सुक हूं।

मुझे लगता है कि StackOverflow के हाइलाइटिंग कोड फिर से बुरी तरह से बेवकूफ है। वे यहाँ बताए गए बाकी गरीब दृष्टिकोणों के रूप में सभी (पुराने नहीं बल्कि सभी) पुराने समान लंगड़े बना रहे हैं। आराम करने के लिए ASCII लगाने के लिए क्या यह लंबे समय से नहीं है? यह अब समझ में नहीं आता है, और यह दिखावा कि यह आपके पास है बस गलत है। यह खराब कोड के लिए बनाता है।


आपका 'सर्वश्रेष्ठ' उत्तर अब तक निकटतम है, लेकिन ऐसा नहीं लगता है कि यह प्रमुख विराम चिह्न या अन्य प्रमुख गैर-लोअरकेस अक्षरों के लिए खाता है। यह मेरे लिए सबसे अच्छा काम करने लगता है (जावा में): ReplaceAll ("(<! <^ ^ ^ ^ \\ p {javaUpperCase}]) (? = [\\ p {javaUpperCase}]"), "");
Rand18a

हम्म। मुझे यकीन नहीं है कि रोमन अंकों को वास्तव में इस उदाहरण में अपरकेस के रूप में गिना जाना चाहिए। अक्षर modifer उदाहरण निश्चित रूप से गिना नहीं जाना चाहिए। यदि आप McDonalds.com पर जाते हैं, तो आप देखेंगे कि यह बिना किसी स्थान के लिखा गया है।
मार्टिन ब्राउन

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

4

बाइनरी वॉरियर, मैंने आपके सुझाए गए कोड का उपयोग किया है, और यह अच्छा है, मेरे पास इसके अलावा सिर्फ एक मामूली है:

public static string AddSpacesToSentence(string text)
{
    if (string.IsNullOrEmpty(text))
        return "";
    StringBuilder newText = new StringBuilder(text.Length * 2);
    newText.Append(text[0]);
            for (int i = 1; i < result.Length; i++)
            {
                if (char.IsUpper(result[i]) && !char.IsUpper(result[i - 1]))
                {
                    newText.Append(' ');
                }
                else if (i < result.Length)
                {
                    if (char.IsUpper(result[i]) && !char.IsUpper(result[i + 1]))
                        newText.Append(' ');

                }
                newText.Append(result[i]);
            }
    return newText.ToString();
}

मैंने एक शर्त जोड़ी है !char.IsUpper(text[i - 1]) । यह एक बग तय करता है, जो 'औसतनॉक्स' जैसी चीज को 'औसत NO X' में बदल देगा, जो जाहिर तौर पर गलत है, क्योंकि इसे 'औसत NOX' पढ़ना चाहिए।

अफसोस की बात है कि अभी भी यह बग है कि यदि आपके पास 'FromAStart' पाठ है, तो आपको 'From Astart' मिल जाएगा।

इसे ठीक करने पर कोई विचार?


शायद ऐसा कुछ काम करेगा: char.IsUpper (पाठ [i]) और& (char.IsLower (पाठ [i - 1])) || (char.IsLower (पाठ [i + 1]))
मार्टिन ब्राउन

1
यह सही है: if (char.IsUpper(text[i]) && !(char.IsUpper(text[i - 1]) && char.IsUpper(text[i + 1])))टेस्ट रिजल्ट: "फ्रॉम स्टार्ट", "फ्रॉम द स्टार्ट", "फ्रॉम ए स्टार्ट" लेकिन i < text.Length - 1अंतिम चरित्र को नजरअंदाज करने और सीमा अपवाद को रोकने के लिए आपको लूप कंडीशन की जरूरत है।
CallMeLaNN

अरे यह तो वही है। ! (a && b) और (! a (b!) क्योंकि निचला = ऊपरी।
CallMeLaNN

3

ये मेरा:

private string SplitCamelCase(string s) 
{ 
    Regex upperCaseRegex = new Regex(@"[A-Z]{1}[a-z]*"); 
    MatchCollection matches = upperCaseRegex.Matches(s); 
    List<string> words = new List<string>(); 
    foreach (Match match in matches) 
    { 
        words.Add(match.Value); 
    } 
    return String.Join(" ", words.ToArray()); 
}

क्या वह C # माना जाता है? यदि हां, तो क्या नाम स्थान सूची में है? क्या आपका मतलब है ArrayList या List <string>?
मार्टिन ब्राउन

सूची <string> ठीक रहेगा। उसके लिए माफ़ करना।
कोरी फॉय

@ मार्टिन उनके पास हमेशा सही सिंटैक्स था, यह केवल मार्कडाउन सिंटैक्स के <pre><code>code</code></pre>बजाय एक ब्लॉक में छिपा हुआ था । उसे (यदि आप वह थे) उसे उखाड़ने की आवश्यकता नहीं है।
जॉर्ज स्टॉकर

3

सुनिश्चित करें कि आप स्ट्रिंग की शुरुआत में रिक्त स्थान नहीं डाल रहे हैं , लेकिन आप उन्हें लगातार राजधानियों के बीच रख रहे हैं । यहाँ कुछ उत्तर उन बिंदुओं में से एक या दोनों को संबोधित नहीं करते हैं। रेगेक्स की तुलना में अन्य तरीके हैं, लेकिन यदि आप इसका उपयोग करना पसंद करते हैं, तो यह प्रयास करें:

Regex.Replace(value, @"\B[A-Z]", " $0")

\Bएक नकार दिया गया है \b, तो यह एक गैर शब्द सीमा का प्रतिनिधित्व करता है,। इसका मतलब है कि पैटर्न "Y" से मेल खाता XYzabcहै, लेकिन नहीं में Yzabcया X Yzabc। एक छोटे से बोनस के रूप में, आप इसे स्ट्रिंग में रिक्त स्थान के साथ उपयोग कर सकते हैं और यह उन्हें दोगुना नहीं करेगा।


3

यह रेगेक्स हर कैपिटल लेटर के सामने एक स्पेस कैरेक्टर रखता है:

using System.Text.RegularExpressions;

const string myStringWithoutSpaces = "ThisIsAStringWithoutSpaces";
var myStringWithSpaces = Regex.Replace(myStringWithoutSpaces, "([A-Z])([a-z]*)", " $1$2");

"$ 1 $ 2" के सामने स्थान को ध्यान में रखें, यही वह है जो इसे पूरा करेगा।

यह परिणाम है:

"This Is A String Without Spaces"

1
यदि आप संख्याओं को अलग करना चाहते हैं, तो इसके बजाय इस रेगेक्स पैटर्न का उपयोग करें:"([A-Z0-9])([a-z]*)"
Matthias Thomann

2

आपके पास पूरी तरह से काम करता है। बस valueइस फ़ंक्शन के रिटर्न मान को पुन: असाइन करने के लिए याद रखें ।

value = System.Text.RegularExpressions.Regex.Replace(value, "[A-Z]", " $0");

2

यहाँ आप इसे SQL में कैसे कर सकते हैं

create  FUNCTION dbo.PascalCaseWithSpace(@pInput AS VARCHAR(MAX)) RETURNS VARCHAR(MAX)
BEGIN
    declare @output varchar(8000)

set @output = ''


Declare @vInputLength        INT
Declare @vIndex              INT
Declare @vCount              INT
Declare @PrevLetter varchar(50)
SET @PrevLetter = ''

SET @vCount = 0
SET @vIndex = 1
SET @vInputLength = LEN(@pInput)

WHILE @vIndex <= @vInputLength
BEGIN
    IF ASCII(SUBSTRING(@pInput, @vIndex, 1)) = ASCII(Upper(SUBSTRING(@pInput, @vIndex, 1)))
       begin 

        if(@PrevLetter != '' and ASCII(@PrevLetter) = ASCII(Lower(@PrevLetter)))
            SET @output = @output + ' ' + SUBSTRING(@pInput, @vIndex, 1)
            else
            SET @output = @output +  SUBSTRING(@pInput, @vIndex, 1) 

        end
    else
        begin
        SET @output = @output +  SUBSTRING(@pInput, @vIndex, 1) 

        end

set @PrevLetter = SUBSTRING(@pInput, @vIndex, 1) 

    SET @vIndex = @vIndex + 1
END


return @output
END

2

@MartinBrown से प्रेरित, सिंपल रेगेक्स की दो लाइन्स, जो आपका नाम सुलझाएगी, जिसमें स्ट्रिंग में कहीं भी एक्रोनॉर्म्स शामिल हैं।

public string ResolveName(string name)
{
   var tmpDisplay = Regex.Replace(name, "([^A-Z ])([A-Z])", "$1 $2");
   return Regex.Replace(tmpDisplay, "([A-Z]+)([A-Z][^A-Z$])", "$1 $2").Trim();
}

मुझे यह समाधान पसंद है। यह छोटा और तेज है। हालांकि, अन्य समाधानों के समान, यह स्ट्रिंग "रेग्युलर" के साथ विफल हो जाता है। मेरे द्वारा हल किए गए हर समाधान "रेगुलर ओ टी"
पाटी गुटी

@PateeGutee ओपी को कैपिटल से पहले जगह चाहिए थी, उन्होंने संक्षिप्त रूप में उल्लेख नहीं किया, हमारे पास उत्पादन कॉड में एक तय है
जॉनी 5

क्या आप ठीक दिखा सकते हैं? मेरे डेटा में इस तरह के तार हैं और यह मुझे गलत परिणाम दे रहा है। धन्यवाद।
पाटे गुटी

@PateeGutee क्षमा करें, आप जो चाहते थे, मैंने उसे गलत समझा। बहुवचन एक अलग मुद्दा है, 'रेगुलरोट्स' आप "रेगुलर ओटी" या "रेगुलर ओटी एस" होने की उम्मीद कर रहे हैं
जॉनी 5

1
@PateeGutee मैंने आपके लिए अपना जवाब अपडेट कर दिया है, मेरा मानना ​​है कि काम करना चाहिए
जॉनी 5


1
static string AddSpacesToColumnName(string columnCaption)
    {
        if (string.IsNullOrWhiteSpace(columnCaption))
            return "";
        StringBuilder newCaption = new StringBuilder(columnCaption.Length * 2);
        newCaption.Append(columnCaption[0]);
        int pos = 1;
        for (pos = 1; pos < columnCaption.Length-1; pos++)
        {               
            if (char.IsUpper(columnCaption[pos]) && !(char.IsUpper(columnCaption[pos - 1]) && char.IsUpper(columnCaption[pos + 1])))
                newCaption.Append(' ');
            newCaption.Append(columnCaption[pos]);
        }
        newCaption.Append(columnCaption[pos]);
        return newCaption.ToString();
    }

1

रूबी में, Regexp के माध्यम से:

"FooBarBaz".gsub(/(?!^)(?=[A-Z])/, ' ') # => "Foo Bar Baz"

1
अरे! माफ़ करना। मुझे याद आया कि यह C # -स्पेशल प्रश्न है और यहाँ पोस्ट किया गया रूबी जवाब :(
आर्टेम

1

मैंने केविन स्ट्रिकर्स का उत्कृष्ट समाधान निकाला और वीबी में परिवर्तित किया। चूंकि मैं .NET 3.5 में बंद हूं, इसलिए मुझे IsNullOrWhiteSpace लिखना पड़ा। यह उसके सभी परीक्षणों को पारित करता है।

<Extension()>
Public Function IsNullOrWhiteSpace(value As String) As Boolean
    If value Is Nothing Then
        Return True
    End If
    For i As Integer = 0 To value.Length - 1
        If Not Char.IsWhiteSpace(value(i)) Then
            Return False
        End If
    Next
    Return True
End Function

<Extension()>
Public Function UnPascalCase(text As String) As String
    If text.IsNullOrWhiteSpace Then
        Return String.Empty
    End If

    Dim newText = New StringBuilder()
    newText.Append(text(0))
    For i As Integer = 1 To text.Length - 1
        Dim currentUpper = Char.IsUpper(text(i))
        Dim prevUpper = Char.IsUpper(text(i - 1))
        Dim nextUpper = If(text.Length > i + 1, Char.IsUpper(text(i + 1)) Or Char.IsWhiteSpace(text(i + 1)), prevUpper)
        Dim spaceExists = Char.IsWhiteSpace(text(i - 1))
        If (currentUpper And Not spaceExists And (Not nextUpper Or Not prevUpper)) Then
            newText.Append(" ")
        End If
        newText.Append(text(i))
    Next
    Return newText.ToString()
End Function

1

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

GitHub पर Humanizer देखें या Nuget।

उदाहरण

"PascalCaseInputStringIsTurnedIntoSentence".Humanize() => "Pascal case input string is turned into sentence"
"Underscored_input_string_is_turned_into_sentence".Humanize() => "Underscored input string is turned into sentence"
"Underscored_input_String_is_turned_INTO_sentence".Humanize() => "Underscored input String is turned INTO sentence"

// acronyms are left intact
"HTML".Humanize() => "HTML"

बस कोशिश की है और पहले लिंक अब टूट गया है। NuGet काम करता है, लेकिन पैकेज मेरे समाधान में संकलित नहीं है। एक अच्छा विचार है, अगर यह काम किया।
फिल्माया गया

1

के लिए एक अच्छा अवसर की तरह लगता है Aggregate। यह विशेष रूप से तेजी से जरूरी नहीं कि पठनीय बनाया गया है।

someString
.Aggregate(
   new StringBuilder(),
   (str, ch) => {
      if (char.IsUpper(ch) && str.Length > 0)
         str.Append(" ");
      str.Append(ch);
      return str;
   }
).ToString();

0

मार्टिन ब्राउन के उत्तर के अलावा, मेरे पास अंक के साथ भी एक मुद्दा था। उदाहरण के लिए: "स्थान 2", या "Jan22" क्रमशः "स्थान 2", और "जन 22" होना चाहिए।

मार्टिन ब्राउन के जवाब का उपयोग करते हुए, ऐसा करने के लिए यहां मेरा नियमित अभिव्यक्ति है:

"((?<=\p{Ll})\p{Lu})|((?!\A)\p{Lu}(?>\p{Ll}))|((?<=[\p{Ll}\p{Lu}])\p{Nd})|((?<=\p{Nd})\p{Lu})"

यहाँ कुछ महान साइटों के लिए यह पता लगाया गया है कि प्रत्येक भाग का क्या अर्थ है:

जावा आधारित नियमित अभिव्यक्ति विश्लेषक (लेकिन अधिकांश के लिए काम करता है .net regex का)

एक्शन स्क्रिप्ट आधारित विश्लेषक

उपरोक्त रेगेक्स एक्शन स्क्रिप्ट साइट पर तब तक काम नहीं करेगा जब तक कि आप सभी के \p{Ll}साथ [a-z], \p{Lu}साथ [A-Z], और \p{Nd}साथ की जगह नहीं लेते [0-9]


0

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

public string AddSpacesBeforeUpperCase(string nonSpacedString)
    {
        if (string.IsNullOrEmpty(nonSpacedString))
            return string.Empty;

        StringBuilder newText = new StringBuilder(nonSpacedString.Length * 2);
        newText.Append(nonSpacedString[0]);

        for (int i = 1; i < nonSpacedString.Length; i++)
        {
            char currentChar = nonSpacedString[i];

            // If it is whitespace, we do not need to add another next to it
            if(char.IsWhiteSpace(currentChar))
            {
                continue;
            }

            char previousChar = nonSpacedString[i - 1];
            char nextChar = i < nonSpacedString.Length - 1 ? nonSpacedString[i + 1] : nonSpacedString[i];

            if (char.IsUpper(currentChar) && !char.IsWhiteSpace(nextChar) 
                && !(char.IsUpper(previousChar) && char.IsUpper(nextChar)))
            {
                newText.Append(' ');
            }
            else if (i < nonSpacedString.Length)
            {
                if (char.IsUpper(currentChar) && !char.IsWhiteSpace(nextChar) && !char.IsUpper(nextChar))
                {
                    newText.Append(' ');
                }
            }

            newText.Append(currentChar);
        }

        return newText.ToString();
    }

0

जो कोई C ++ फ़ंक्शन की तलाश में है, उसी प्रश्न का उत्तर देने के लिए, आप निम्न का उपयोग कर सकते हैं। यह @Binary Worrier द्वारा दिए गए जवाब के बाद मॉडलिंग की गई है। यह विधि बस स्वचालित रूप से © को संरक्षित करती है।

using namespace std;

void AddSpacesToSentence(string& testString)
        stringstream ss;
        ss << testString.at(0);
        for (auto it = testString.begin() + 1; it != testString.end(); ++it )
        {
            int index = it - testString.begin();
            char c = (*it);
            if (isupper(c))
            {
                char prev = testString.at(index - 1);
                if (isupper(prev))
                {
                    if (index < testString.length() - 1)
                    {
                        char next = testString.at(index + 1);
                        if (!isupper(next) && next != ' ')
                        {
                            ss << ' ';
                        }
                    }
                }
                else if (islower(prev)) 
                {
                   ss << ' ';
                }
            }

            ss << c;
        }

        cout << ss.str() << endl;

परीक्षण स्ट्रिंग मैंने इस फ़ंक्शन के लिए उपयोग किया है, और परिणाम हैं:

  • "हैलो वर्ल्ड" -> "हैलो वर्ल्ड"
  • "हैलोवर्ल्ड" -> "हैलो वर्ल्ड"
  • "HelloABCWorld" -> "हैलो एबीसी वर्ल्ड"
  • "HelloWorldABC" -> "हैलो वर्ल्ड एबीसी"
  • "ABCHelloWorld" -> "एबीसी हैलो वर्ल्ड"
  • "एबीसी हेलो वर्ल्ड" -> "एबीसी हेलो वर्ल्ड"
  • "ABCHELLOWORLD" -> "ABCHELLOWORLD"
  • "ए" -> "ए"

0

एक इनपुट स्ट्रिंग के लिए C # समाधान जिसमें केवल ASCII वर्ण होते हैं। रेगुलर एक्सप्रेशन से शामिल किया गया है नकारात्मक lookbehind कि स्ट्रिंग की शुरुआत में प्रकट होता है एक पूंजी (अपर केस) पत्र की अनदेखी करने के। वांछित स्ट्रिंग वापस करने के लिए Regex.Replace () का उपयोग करता है ।

इसके अलावा regex101.com डेमो देखें ।

using System;
using System.Text.RegularExpressions;

public class RegexExample
{
    public static void Main()
    {
        var text = "ThisStringHasNoSpacesButItDoesHaveCapitals";

        // Use negative lookbehind to match all capital letters
        // that do not appear at the beginning of the string.
        var pattern = "(?<!^)([A-Z])";

        var rgx = new Regex(pattern);
        var result = rgx.Replace(text, " $1");
        Console.WriteLine("Input: [{0}]\nOutput: [{1}]", text, result);
    }
}

अपेक्षित उत्पादन:

Input: [ThisStringHasNoSpacesButItDoesHaveCapitals]
Output: [This String Has No Spaces But It Does Have Capitals]

अद्यतन: यहां एक भिन्नता है जो समरूपता (ऊपरी-क्रम के अक्षरों के अनुक्रम) को भी संभाल लेगी ।

इसके अलावा regex101.com डेमो और ideone.com डेमो देखें

using System;
using System.Text.RegularExpressions;

public class RegexExample
{
    public static void Main()
    {
        var text = "ThisStringHasNoSpacesASCIIButItDoesHaveCapitalsLINQ";

        // Use positive lookbehind to locate all upper-case letters
        // that are preceded by a lower-case letter.
        var patternPart1 = "(?<=[a-z])([A-Z])";

        // Used positive lookbehind and lookahead to locate all
        // upper-case letters that are preceded by an upper-case
        // letter and followed by a lower-case letter.
        var patternPart2 = "(?<=[A-Z])([A-Z])(?=[a-z])";

        var pattern = patternPart1 + "|" + patternPart2;
        var rgx = new Regex(pattern);
        var result = rgx.Replace(text, " $1$2");

        Console.WriteLine("Input: [{0}]\nOutput: [{1}]", text, result);
    }
}

अपेक्षित उत्पादन:

Input: [ThisStringHasNoSpacesASCIIButItDoesHaveCapitalsLINQ]
Output: [This String Has No Spaces ASCII But It Does Have Capitals LINQ]

0

यहाँ अधिक गहन समाधान है जो शब्दों के सामने स्थान नहीं डालता है:

नोट: मैंने कई Regexs का उपयोग किया है (संक्षिप्त नहीं है लेकिन यह समरूप और एकल अक्षर शब्दों को भी हैंडल करेगा)

Dim s As String = "ThisStringHasNoSpacesButItDoesHaveCapitals"
s = System.Text.RegularExpressions.Regex.Replace(s, "([a-z])([A-Z](?=[A-Z])[a-z]*)", "$1 $2")
s = System.Text.RegularExpressions.Regex.Replace(s, "([A-Z])([A-Z][a-z])", "$1 $2")
s = System.Text.RegularExpressions.Regex.Replace(s, "([a-z])([A-Z][a-z])", "$1 $2")
s = System.Text.RegularExpressions.Regex.Replace(s, "([a-z])([A-Z][a-z])", "$1 $2") // repeat a second time

इन :

"ThisStringHasNoSpacesButItDoesHaveCapitals"
"IAmNotAGoat"
"LOLThatsHilarious!"
"ThisIsASMSMessage"

बाहर :

"This String Has No Spaces But It Does Have Capitals"
"I Am Not A Goat"
"LOL Thats Hilarious!"
"This Is ASMS Message" // (Difficult to handle single letter words when they are next to acronyms.)

यह आउटपुट "इस स्ट्रिंग में NoSpaces लेकिन ItDoes है कैपिटल"
एंडी रॉबिन्सन

हाय @AndyRobinson, धन्यवाद। मैं कई Regex की जगह का उपयोग करने के लिए बदल गया। यकीन नहीं है कि अगर कोई अधिक संक्षिप्त तरीका है, लेकिन यह अब काम करता है।
CrazyTim

0

पिछली सभी प्रतिक्रियाएँ बहुत जटिल दिखीं।

मेरे पास स्ट्रिंग थी जिसमें राजधानियों और _ का मिश्रण था, इसलिए, स्ट्रिंग .eplace () को _, "" बनाने के लिए और निम्नलिखित का उपयोग बड़े अक्षरों में स्थान जोड़ने के लिए किया।

for (int i = 0; i < result.Length; i++)
{
    if (char.IsUpper(result[i]))
    {
        counter++;
        if (i > 1) //stops from adding a space at if string starts with Capital
        {
            result = result.Insert(i, " ");
            i++; //Required** otherwise stuck in infinite 
                 //add space loop over a single capital letter.
        }
    }
}

0

बाइनरी वॉरियर के जवाब से प्रेरित होकर मैंने इस पर जोर दिया।

यहाँ परिणाम है:

/// <summary>
/// String Extension Method
/// Adds white space to strings based on Upper Case Letters
/// </summary>
/// <example>
/// strIn => "HateJPMorgan"
/// preserveAcronyms false => "Hate JP Morgan"
/// preserveAcronyms true => "Hate JPMorgan"
/// </example>
/// <param name="strIn">to evaluate</param>
/// <param name="preserveAcronyms" >determines saving acronyms (Optional => false) </param>
public static string AddSpaces(this string strIn, bool preserveAcronyms = false)
{
    if (string.IsNullOrWhiteSpace(strIn))
        return String.Empty;

    var stringBuilder = new StringBuilder(strIn.Length * 2)
        .Append(strIn[0]);

    int i;

    for (i = 1; i < strIn.Length - 1; i++)
    {
        var c = strIn[i];

        if (Char.IsUpper(c) && (Char.IsLower(strIn[i - 1]) || (preserveAcronyms && Char.IsLower(strIn[i + 1]))))
            stringBuilder.Append(' ');

        stringBuilder.Append(c);
    }

    return stringBuilder.Append(strIn[i]).ToString();
}

10000000 पुनरावृत्तियों और विभिन्न स्ट्रिंग लंबाई और संयोजनों को चलाने वाले स्टॉपवॉच का उपयोग करके परीक्षण किया।

बाइनरी वॉरियर उत्तर की तुलना में औसतन 50% (शायद थोड़ा अधिक)।


0
    private string GetProperName(string Header)
    {
        if (Header.ToCharArray().Where(c => Char.IsUpper(c)).Count() == 1)
        {
            return Header;
        }
        else
        {
            string ReturnHeader = Header[0].ToString();
            for(int i=1; i<Header.Length;i++)
            {
                if (char.IsLower(Header[i-1]) && char.IsUpper(Header[i]))
                {
                    ReturnHeader += " " + Header[i].ToString();
                }
                else
                {
                    ReturnHeader += Header[i].ToString();
                }
            }

            return ReturnHeader;
        }

        return Header;
    }

0

इसमें एक समरूप और संक्षिप्त प्लूरल शामिल हैं और स्वीकृत उत्तर की तुलना में थोड़ा तेज है:

public string Sentencify(string value)
{
    if (string.IsNullOrWhiteSpace(value))
        return string.Empty;

    string final = string.Empty;
    for (int i = 0; i < value.Length; i++)
    {
        if (i != 0 && Char.IsUpper(value[i]))
        {
            if (!Char.IsUpper(value[i - 1]))
                final += " ";
            else if (i < (value.Length - 1))
            {
                if (!Char.IsUpper(value[i + 1]) && !((value.Length >= i && value[i + 1] == 's') ||
                                                     (value.Length >= i + 1 && value[i + 1] == 'e' && value[i + 2] == 's')))
                    final += " ";
            }
        }

        final += value[i];
    }

    return final;
}

इन परीक्षणों को पास करता है:

string test1 = "RegularOTs";
string test2 = "ThisStringHasNoSpacesASCIIButItDoesHaveCapitalsLINQ";
string test3 = "ThisStringHasNoSpacesButItDoesHaveCapitals";

स्वीकृत जवाब उस मामले से संबंधित है जहां मूल्य शून्य है
क्रिस एफ कैरोल

यह आउटपुट के सामने एक अतिरिक्त स्थान जोड़ता है, अर्थात HireDate => "किराया तिथि"। एक अंतिम की जरूरत है। श्रीमंत या कुछ और। मुझे लगता है कि अन्य जवाबों में से एक नीचे इंगित कर रहा है, लेकिन पुन: व्यवस्थित होने के कारण मुझे यकीन नहीं है कि यदि वह आपसे बात कर रहा है क्योंकि उसका जवाब RegEx आधारित है।
b_levitt

अच्छी पकड़ ... को मेरे परीक्षणों में एक शुरुआत और अंतिम मार्कर जोड़ना चाहिए ... अब तय किया गया।
सेर्गे सगन

यहां पोस्ट किए गए अन्य समाधान के समान, यह स्ट्रिंग "रेग्युलर" के साथ विफल हो जाता है। यह "रेगुलर ओ टीएस"
पाटे गुटी

संक्षिप्त नाम बढ़ाने के लिए धन्यवाद, मैंने इसके लिए भी काम करना अपडेट किया है।
सर्ज सगन

0

इसके साथ एक कार्यान्वयन fold, जिसे भी जाना जाता है Aggregate:

    public static string SpaceCapitals(this string arg) =>
       new string(arg.Aggregate(new List<Char>(),
                      (accum, x) => 
                      {
                          if (Char.IsUpper(x) &&
                              accum.Any() &&
                              // prevent double spacing
                              accum.Last() != ' ' &&
                              // prevent spacing acronyms (ASCII, SCSI)
                              !Char.IsUpper(accum.Last()))
                          {
                              accum.Add(' ');
                          }

                          accum.Add(x);

                          return accum;
                      }).ToArray());

अनुरोध के अलावा, यह कार्यान्वयन सही ढंग से अग्रणी, आंतरिक, अनुगामी रिक्त स्थान और समरूपता बचाता है, उदाहरण के लिए,

" SpacedWord " => " Spaced Word ",  

"Inner Space" => "Inner Space",  

"SomeACRONYM" => "Some ACRONYM".

0

लोअर केस लेटर्स, अपर केस लेटर्स या अंकों के बाद स्पेस जोड़ने का सरल तरीका।

    string AddSpacesToSentence(string value, bool spaceLowerChar = true, bool spaceDigitChar = true, bool spaceSymbolChar = false)
    {
        var result = "";

        for (int i = 0; i < value.Length; i++)
        {
            char currentChar = value[i];
            char nextChar = value[i < value.Length - 1 ? i + 1 : value.Length - 1];

            if (spaceLowerChar && char.IsLower(currentChar) && !char.IsLower(nextChar))
            {
                result += value[i] + " ";
            }
            else if (spaceDigitChar && char.IsDigit(currentChar) && !char.IsDigit(nextChar))
            {
                result += value[i] + " ";
            }
            else if(spaceSymbolChar && char.IsSymbol(currentChar) && !char.IsSymbol(nextChar))
            {
                result += value[i];
            }
            else
            {
                result += value[i];
            }
        }

        return result;
    }

1
कोड-केवल उत्तर हतोत्साहित किए जाते हैं। कृपया संपादित करें पर क्लिक करें और कुछ शब्दों को जोड़ते हुए कहें कि आपका कोड प्रश्न को कैसे संबोधित करता है, या शायद समझाएं कि आपका उत्तर पिछले उत्तर / उत्तरों से कैसे भिन्न है। समीक्षा से
निक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.