Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace first word with last word in C#

Tags:

c#

regex

replace

I want to replace the following line in C#. Replace first word with last word. I have to remove '[' and ']' from last word as well.

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

Output should be

string newString="a18943 abc def abc"; 

Thanks

like image 734
NETQuestion Avatar asked Nov 11 '09 22:11

NETQuestion


2 Answers

string newString = Regex.Replace(oldString, @"^(\w+)(.+) \[(\w+)\]$", "$3$2");
like image 65
Martin Jonáš Avatar answered Nov 06 '22 13:11

Martin Jonáš


Just for fun, I wrote a little benchmark to perf-test all these answers (including my other answer above). Here's results on my workstation (32-bit Core 2 Duo @ 2.66GHz) for 5M repetitions using a Release build :

  • LINQ : 10.545 seconds
  • my Split + StringBuilder way : 3.633 seconds
  • wipeck's Split-and-Join way! : 3.32 seconds
  • (uncompiled) regex : 3.845 seconds
  • (compiled) regex : 12.431 seconds

Results: wipeck's Split-and-Join solution wins, but the (OP-selected) regex solution was only 15% slower, which surprised me. I was expecting 100% or more worse. Kudos to the .NET Regex developers for speed.

My own solution (using Split and StringBuilder) was, I thought, optimized for speed, but requires a lot more code and doesn't actually make it fast. Doh!

Most surprisingly, I tried a compiled regex solution and it was almost 3x slower than the uncompiled regex (and I didn't include the compilation time in the results-- including compilation it'd be even worse). So much for compiled regex perf advantage.

LINQ was, as I expected, really slow-- the overhead of all those extra objects and method calls really adds up.

Here's the test code:

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");
            }
        }
    }
}
like image 5
Justin Grant Avatar answered Nov 06 '22 12:11

Justin Grant