2009-12-28 7 views
9

np chciałbym rozdzielić:Jak oddzielić charakter i numer części z łańcucha

  • OS234 do OS i 234
  • AA4230 do AA i 4230

Użyłem następujących trywialne rozwiązanie, ale jestem pewien, że powinno istnieć bardziej wydajne i niezawodne rozwiązanie.

private void demo() 
    { string cell="ABCD4321"; 
     int a = getIndexofNumber(cell); 
     string Numberpart = cell.Substring(a, cell.Length - a); 
     row = Convert.ToInt32(rowpart); 
     string Stringpart = cell.Substring(0, a); 
    } 

private int getIndexofNumber(string cell) 
     { 
      int a = -1, indexofNum = 10000; 
      a = cell.IndexOf("0"); if (a > -1) { if (indexofNum > a) { indexofNum = a; } } 
      a = cell.IndexOf("1"); if (a > -1) { if (indexofNum > a) { indexofNum = a; } } 
      a = cell.IndexOf("2"); if (a > -1) { if (indexofNum > a) { indexofNum = a; } } 
      a = cell.IndexOf("3"); if (a > -1) { if (indexofNum > a) { indexofNum = a; } } 
      a = cell.IndexOf("4"); if (a > -1) { if (indexofNum > a) { indexofNum = a; } } 
      a = cell.IndexOf("5"); if (a > -1) { if (indexofNum > a) { indexofNum = a; } } 
      a = cell.IndexOf("6"); if (a > -1) { if (indexofNum > a) { indexofNum = a; } } 
      a = cell.IndexOf("7"); if (a > -1) { if (indexofNum > a) { indexofNum = a; } } 
      a = cell.IndexOf("8"); if (a > -1) { if (indexofNum > a) { indexofNum = a; } } 
      a = cell.IndexOf("9"); if (a > -1) { if (indexofNum > a) { indexofNum = a; } } 

      if (indexofNum != 10000) 
      { return indexofNum; } 
      else 
      { return 0; } 


     } 

Odpowiedz

1

Użyłem odpowiedź bniwredyc, aby uzyskać ulepszoną wersję mojej rutyny:

private void demo() 
     { 
      string cell = "ABCD4321"; 
      int row, a = getIndexofNumber(cell); 
      string Numberpart = cell.Substring(a, cell.Length - a); 
      row = Convert.ToInt32(Numberpart); 
      string Stringpart = cell.Substring(0, a); 
     } 

     private int getIndexofNumber(string cell) 
     { 
      int indexofNum=-1; 
      foreach (char c in cell) 
      { 
       indexofNum++; 
       if (Char.IsDigit(c)) 
       { 
        return indexofNum; 
       } 
      } 
      return indexofNum; 
     } 
5

używać LINQ to zrobić

string str = "OS234"; 

var digits = from c in str 
      select c 
      where Char.IsDigit(c); 

var alphas = from c in str 
      select c 
      where !Char.IsDigit(c); 
+0

+1 czysty roztwór –

+2

To wydaje się być dobrym rozwiązaniem, ale niestety .net 2.0 użytkownicy nie mogli używać LINQ – Thunder

+0

Polecam - uaktualnienie do C# 3.0. –

15

Wyrażenia regularne są najlepiej nadaje się do tego rodzaju pracy:

using System.Text.RegularExpressions; 

Regex re = new Regex(@"([a-zA-Z]+)(\d+)"); 
Match result = re.Match(input); 

string alphaPart = result.Groups[1].Value; 
string numberPart = result.Groups[2].Value; 
+1

Może chcesz dodać dwie linie do tej odpowiedzi: string alphaPart = result.Groups [1]; string numberPart = result.Groups [2]; –

+0

Poniżej wydaje się bardziej kompletne rozwiązanie: Regex re = new Regex (@ "([a-zA-Z] +) (\ d +)"); Wynik meczu = re.Match ("as23"); string alphaPart = result.Groups [1] .ToString(); string numberPart = result.Groups [2] .ToString(); – Thunder

+1

Czy to nie 'result.Groups [1] .Value'? –

3

Wszyscy i ich matka daje rozwiązanie za pomocą wyrażenia regularnego, tak Oto jeden, który nie jest:

// s is string of form ([A-Za-z])*([0-9])* ; char added 
int index = s.IndexOfAny(new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }); 
string chars = s.Substring(0, index); 
int num = Int32.Parse(s.Substring(index)); 
1

Czy robisz to w celu sortowania? Jeśli tak, pamiętaj, że Regex może zabić wydajność dużych list. Często używam AlphanumComparer, który jest ogólnym rozwiązaniem tego problemu (może obsłużyć dowolną sekwencję liter i cyfr w dowolnej kolejności). Uważam, że dostosowałem go z this page.

Nawet jeśli nie sortujesz, używając metody znak po znaku (jeśli masz zmienną długość) lub prostego podciągu/parsowania (jeśli są ustalone) będzie o wiele wydajniejszy i łatwiejszy do test niż Regex.

1

.NET 2.0 kompatybilne, bez regex

public class Result 
{ 
    private string _StringPart; 
    public string StringPart 
    { 
     get { return _StringPart; } 
    } 

    private int _IntPart; 
    public int IntPart 
    { 
     get { return _IntPart; } 
    } 

    public Result(string stringPart, int intPart) 
    { 
     _StringPart = stringPart; 
     _IntPart = intPart; 
    } 
} 

class Program 
{ 
    public static Result GetResult(string source) 
    { 
     string stringPart = String.Empty; 
     int intPart; 
     var buffer = new StringBuilder(); 
     foreach (char c in source) 
     { 
      if (Char.IsDigit(c)) 
      { 
       if (stringPart == String.Empty) 
       { 
        stringPart = buffer.ToString(); 
        buffer.Remove(0, buffer.Length); 
       } 
      } 

      buffer.Append(c); 
     } 

     if (!int.TryParse(buffer.ToString(), out intPart)) 
     { 
      return null; 
     } 

     return new Result(stringPart, intPart); 
    } 

    static void Main(string[] args) 
    { 
     Result result = GetResult("OS234"); 
     Console.WriteLine("String part: {0} int part: {1}", result.StringPart, result.IntPart); 
     result = GetResult("AA4230 "); 
     Console.WriteLine("String part: {0} int part: {1}", result.StringPart, result.IntPart); 
     result = GetResult("ABCD4321"); 
     Console.WriteLine("String part: {0} int part: {1}", result.StringPart, result.IntPart); 
     Console.ReadKey(); 
    } 
} 
+0

Wygląda na to, że zostało zaprojektowane! –

+0

@this .__ curious_geek yep. Lubię rozwiązanie Jasons. – bniwredyc

-1

użytku Splitu do seprate ciąg od żądło tej karcie Użyj \ t i przestrzeni

string s = "sometext\tsometext\tsometext"; 
string[] split = s.Split('\t'); 

teraz masz tablicę ciągów, które chcesz zbyt łatwe

0

Jeśli chcesz rozwiązać więcej wystąpień char następuje numer lub odwrotnie można użyć

private string SplitCharsAndNums(string text) 
{ 
    var sb = new StringBuilder(); 
    for (var i = 0; i < text.Length - 1; i++) 
    { 
     if ((char.IsLetter(text[i]) && char.IsDigit(text[i+1])) || 
      (char.IsDigit(text[i]) && char.IsLetter(text[i+1]))) 
     { 
      sb.Append(text[i]); 
      sb.Append(" "); 
     } 
     else 
     { 
      sb.Append(text[i]); 
     } 
    } 

    sb.Append(text[text.Length-1]); 

    return sb.ToString(); 
} 

A potem

var text = SplitCharsAndNums("asd1 asas4gr5 6ssfd"); 
var tokens = text.Split(' '); 
0

bardzo podoba mi jason's answer. Nie potrzebujemy tutaj wyrażeń regularnych. Proponowane rozwiązanie w celu wprowadzania, jak "uchwyt H1N1":

public static IEnumerable<string> SplitAlpha(string input) 
{ 
    var words = new List<string> { string.Empty }; 
    for (var i = 0; i < input.Length; i++) 
    { 
     words[words.Count-1] += input[i]; 
     if (i + 1 < input.Length && char.IsLetter(input[i]) != char.IsLetter(input[i + 1])) 
     { 
      words.Add(string.Empty); 
     } 
    } 
    return words; 
} 

Rozwiązanie to liniowa (O (n)).

ouput

"H1N1" -> ["H", "1", "N", "1"] 
"H" -> ["H"] 
"GH1N12" -> ["GH", "1", "N", "12"] 
"OS234" -> ["OS", "234"] 
Powiązane problemy