2012-03-28 10 views
7

Mam ten ciąg:najbardziej skutecznym sposobem na oddzielnym ciąg

„B82V16814133260”

co byłoby najbardziej skutecznym sposobem na zdobycie dwóch ciągów z niego:

lewa część wyrażenie: " B82V " Ciąg części:" 16814133260 "

Zasada jest taka: weź wszystkie liczby po prawej stronie i utwórz z nich łańcuch, a następnie weź przypomnienie i umieść je w innym ciągu.

To jest moje rozwiązanie, ale jest zbyt obszerne! Jak to zrobić krótko i sprawnie?

 String leftString = ""; 
     String rightString=""; 

     foreach (char A in textBox13.Text.Reverse()) 
     { 
      if (Char.IsNumber(A)) 
      { 
       rightString += A; 
      } 
      else 
      { 
       break; 
      } 
     } 

     char[] arr = rightString.ToArray(); 
     Array.Reverse(arr); 

     rightString=new string(arr); 
     leftString = textBox13.Text.Replace(rightString, ""); 
+2

co masz na myśli mówiąc "sprawne"? Wydajne w pamięci lub wydajności? – Tigran

+0

Z ciekawości, dlaczego twoje rozwiązanie jest "zbyt nieporęczne"? Wydaje mi się, że jest to dla mnie dobra funkcja. – Bob2Chiv

+2

Założę odpowiedni Regex, ale przysięgam na boga, jeśli ktoś inny opublikuje go pierwszy ... – mowwwalker

Odpowiedz

14

Daje to co czekasz:

var given = "B82V16814133260"; 
var first = given.TrimEnd("".ToCharArray()); 
var rest = given.Substring(first.Length); 

Console.Write("{0} -> {1} -- {2}", given, first, rest); 
// B82V16814133260 -> B82V -- 16814133260 
+0

+1: Podczas teoretycznego skanowania ciąg do 'ch < '0' || ch > '9'', a następnie dzielenie na indeks brzmi jak najszybszy, to wymaga aplikacji naukowej, aby powiedzieć różnicę (być może). – Jon

+0

Wow, to jest boskie! – Andrew

+3

Eleganckie rozwiązanie. Nie wiedziałem o TrimEnd. – captncraig

4

ten powinien być bardzo szybki:

int index = text.Length - 1; 
while (index >= 0 && Char.IsDigit(text[index])) 
{ 
    index--; 
} 
string left = text.Substring(0, index + 1); 
string right = text.Substring(index + 1); 
+0

Bardzo szybko w porównaniu do czego? –

+0

@AshBurlaczenko: nie ma niepotrzebnych alokacji 'ciągu',' cofania' ciągu znaków i żadnego przydziału 'tablica'. * Powinien * być szybszy. – Tigran

+0

Właściwie wybrałbym tę odpowiedź najprawdopodobniej jak poprawną, ponieważ jest wyraźniejsza i * powinna * być szybsza od najbardziej głosowanej, nawet jeśli powinna przyznać, że większość głosujących jest zdecydowanie "lepsza". – Tigran

1

Lubię LINQ.

var s = "B82V16814133260"; 
    var lastNonNumeric = s.Reverse().Where(x => !char.IsDigit(x)).FirstOrDefault(); 
    var index = s.LastIndexOf(lastNonNumeric); 
    var secondString = s.Substring(index + 1); 
    var firstString = s.Substring(0, index+1); 

Prawdopodobnie nie jest to najlepsze lub najbardziej niezawodne rozwiązanie, ale działa dla twojego ciągu testowego.

+0

Odwrócenie byłoby marnowaniem wysiłku, ponieważ nie trzeba utrzymywać odwrotnego wyniku. s.Last (ch => '0' <= ch && ch <= '9') będzie szybszy. –

+0

Zgadzam się. Wciąż nie jest tak dobry jak rozwiązanie Austina, więc nie będę się tym zajmował. – captncraig

5

Cóż, druga odpowiedź jest chyba lepiej, ale napisałem to tak, więc jestem delegowania go:

Potrzeby:

using System.Text.RegularExpressions; 

Kod:

string str = "B82V16814133260"; 
string[] match = Regex.match(str, @"^([\d\w]+?\w)(\d+)$").Groups; 
string left = match[1]; 
string right = match[2]; 
+0

to także bardzo fajne rozwiązanie! – Andrew

+1

@walkerneo to tylko zabawny fakt, uruchomienie tego regexu (skompilowane regex, kompilacja wydania) zajęło 1605.3 sekund, czyli 856,4 razy dłużej). Jeśli więc szybkość jest "efektywna", wyrażenie regularne nie jest "wydajne". – payo

+0

@payo, W porządku, dzięki, założyłem tyle. Jeśli jego wymagania zmienią się, aby ciąg nie kończył się tylko cyframi, łatwiej będzie to zmienić. Nie mogę powiedzieć, czy jest to możliwe w jego sytuacji, a mimo wszystko wiem, że te struny będą zawsze w tym samym formacie, ale wciąż, nigdy nie wiadomo. – mowwwalker

0
string Source = textBox13.Text; 

for (i = Source.Length - 1; i >=0; i--) 
{ 
     if (! Char.IsNumber(Source[i]) 
     break; 
} 

string leftString = Source.Left(i+1); 
string rightString = Source.Right(i+1,Source.Length-i-1); 
2

Przeczytałem "najbardziej efektywny" jako "najszybszy".

Napisałem szybki test z długim ciągiem, działającym 10 milionów razy.

rozwiązanie Austina używać TrimEnd prowadził w 4.649s

Moje rozwiązanie prowadził w 1,927 sekund

int j = given.Length - 1; 

    for (; j >= 0; j--) 
    { 
     char c = given[j]; 
     if (c < '0' || c > '9') 
     { 
     break; 
     } 
    } 

    var first = given.Substring(0, j + 1); 
    var rest = given.Substring(j + 1); 

Zauważ, że mój buduje nie były debugowania (w debugowania, moje rozwiązanie jest wolniejszy, ale to dlatego, TrimEnd nie działa w bitach debugowania). Tak więc, jeśli uruchamiasz mój kod w aplikacji i budujesz debugowanie, będzie wolniej.

+0

+1 dla czasu kopalni. –

Powiązane problemy