2009-11-11 15 views
8

Chcę zastąpić następujący wiersz w C#. Zastąp pierwsze słowo ostatnim słowem. Muszę również usunąć słowo "[" i "]" z ostatniego słowa.Zastąp pierwsze słowo ostatnim słowem w C#

string oldString = "200 abc def abc [a18943]" 

Wyjście powinno być

string newString="a18943 abc def abc"; 

Dzięki

Odpowiedz

17
string newString = Regex.Replace(oldString, @"^(\w+)(.+) \[(\w+)\]$", "$3$2"); 
+0

+1, bardzo zwięzły. –

+0

To działało Po prostu chcę zrozumieć, jak to działa. Czyste. – NETQuestion

+0

Bardzo czyste. Lubię to. Zastanawiam się tylko, czy RegEx jest tu przesadny? –

0

Oto jeden ze sposobów, aby to zrobić. Zauważ, że zakładam, że ciąg ma co najmniej 1 słowo.

string oldString = "200 abc def abc [a18943]"; 
string[] words = oldString.Split(' '); 
StringBuilder sb = new StringBuilder(words[words.Length-1].Trim('[', ']')); 
for (int i = 1; i < words.Length-1; i++) 
{ 
    sb.Append (" "); 
    sb.Append (words[i]); 
} 
string newString = sb.ToString(); 

OOPS, poprawiono literówkę powyżej. Służą mi do napisania kodu bez kompilacji. :-)

+1

można również użyć .Trim („[”, „]”) aby pozbyć się ze wsporników, które mogą być trochę czystsze zakładając, że ostatnie słowo zawsze zaczyna się i kończy nawiasy. –

+0

Dobry pomysł - Trim jest również znacznie, znacznie szybszy - skraca czas potrzebny do uruchomienia go prawie w połowie. Aktualizuję teraz. –

0

Jest brzydki, ale działa.

string[] a = oldString.Split(' '); 
var result = a.Skip(a.Length-1) 
      .Select(w => w.Replace("[","").Replace("]","")) 
      .Concat(a.Take(a.Length -1).Skip(1)).ToArray(); 

var newString = string.Join(" ", result); 
+0

również, wynik nie jest łańcuchem znaków, jest System.Linq.Enumerable.ConcatIterator –

+0

Od czasu edycji - newString będzie oczywiście zawierał spłaszczony ciąg. –

+0

Rozumiem. BTW, perf z tego jest ponad 3 razy gorszy od zwycięskiego (regex) rozwiązania. Prawdopodobnie nie zrobi to wielkiej różnicy, ponieważ nawet najwolniejsze rozwiązanie pracowało z prędkością 400k na sekundę na moim (powolnym) komputerze, ale myślę, że rozwiązanie regexa pokonuje rozwiązanie LINQ z dużym marginesem, przynajmniej w tym przypadku. –

1

Spróbuj:

Regex  : ^\w+(.*\s)\[(\w+)]$ 
Replacement : $2$1 
4
 string oldString = "200 abc def abc [a18943]"; 
     string[] values = oldString.Split(' '); 
     string lastWord = values[values.Length - 1].Trim('[', ']'); 
     values[0] = lastWord; 
     string newString = string.Join(" ", values, 0, values.Length - 1); 
5

Tak dla zabawy, pisałem trochę odniesienia do perf-przetestować wszystkie te odpowiedzi (w tym inne moją odpowiedź powyżej). Oto wyniki w mojej stacji roboczej (32-bitowy Core 2 Duo @ 2.66GHz) dla 5M powtórzeń przy użyciu kompilacji Release:

  • LINQ: 10.545 sekundy
  • mój Podział + StringBuilder sposób: 3,633 sekund
  • podziału wipeck za i dołącz do drogi! : 3,32 sekund
  • (Nieskompilowany) regex: 3.845 sek
  • (zestawiane) regex: 12.431 s

Wyniki: wipeck jest dzielona i-Dołącz roztwór wygrywa, ale (PO wybrane) roztworu regex był tylko 15% wolniej, co mnie zaskoczyło. Spodziewałem się 100% lub więcej gorzej. Kudos dla programistów .NET Regex dla szybkości.

Moje własne rozwiązanie (używając Split i StringBuilder) było, jak sądziłem, zoptymalizowane pod kątem szybkości, ale wymaga znacznie więcej kodu i nie robi tego szybko. Doh!

Najbardziej zaskakujące, próbowałem skompilowanego rozwiązania regex i było prawie 3x wolniejsze niż nieskompilowane wyrażenie regularne (i nie uwzględniłem czasu kompilacji w wynikach - włącznie z kompilacją byłoby jeszcze gorzej). Tyle dla skompilowanej przewagi regex perf.

LINQ było, jak się spodziewałem, bardzo powolne - nadmiar wszystkich tych dodatkowych obiektów i wywołań metodowych naprawdę się sumuje.

Oto kod testu:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Text.RegularExpressions; 

class Timer : IDisposable 
{ 
    private DateTime _start; 
    private string _name; 

    public Timer(string name) 
    { 
     _name = name; 
     _start = DateTime.Now; 
    } 
    public void Dispose() 
    { 
     TimeSpan taken = DateTime.Now - _start; 
     Console.WriteLine(string.Format ("{0} : {1} seconds", _name, taken.TotalMilliseconds/1000.0)); 
    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     int reps = 5000000; 
     string oldString = "200 abc def abc [a18943]"; 

     using (new Timer("LINQ")) 
     { 
      for (int n = 0; n < reps; n++) 
      { 
       string[] a = oldString.Split(' '); 
       var result = a.Skip(a.Length - 1) 
          .Select(w => w.Replace("[", "").Replace("]", "")) 
          .Concat(a.Take(a.Length - 1).Skip(1)).ToArray(); 

       var newString = string.Join(" ", result); 
      } 
     } 

     using (new Timer("my Split + StringBuilder way")) 
     { 
      for (int n = 0; n < reps; n++) 
      { 
       string[] words = oldString.Split(' '); 
       StringBuilder sb = new StringBuilder(words[words.Length - 1].Trim('[', ']')); 
       for (int i = 1; i < words.Length - 1; i++) 
       { 
        sb.Append(' '); 
        sb.Append(words[i]); 
       } 
       string newString = sb.ToString(); 
      } 
     } 

     using (new Timer("wipeck's Split-and-Join way!")) 
     { 
      for (int n = 0; n < reps; n++) 
      { 
       string valueString = "200 abc def abc [a18943]"; 
       string[] values = valueString.Split(' '); 
       string lastWord = values[values.Length - 1]; 
       lastWord = lastWord.Trim('[', ']'); 
       values[0] = lastWord; 
       string movedValueString = string.Join(" ", values, 0, values.Length - 1); 
      } 
     } 

     using (new Timer("(uncompiled) regex")) 
     { 
      for (int n = 0; n < reps; n++) 
      { 
       string newString = Regex.Replace(@"^(\w+)(.+) \[(\w+)\]$", oldString, "$3$2"); 
      } 
     } 

     Regex regex = new Regex(@"^(\w+)(.+) \[(\w+)\]$", RegexOptions.Compiled); 
     string newStringPreload = regex.Replace(oldString, "$3$2"); 
     using (new Timer("(compiled) regex")) 
     { 
      for (int n = 0; n < reps; n++) 
      { 
       string newString = regex.Replace(oldString, "$3$2"); 
      } 
     } 
    } 
} 
+0

Nice! Dzięki za zamieszczenie tego. Chociaż mój kod może nie być aż tak elegancki, to robi to zadanie :) –

Powiązane problemy