6

string format is always like this "FirstName=ABC;LastName=XZY;Username=User1;Password=1234".

I need the only UserName value (which is 'User1' in this case). I wanna achieve this in minimum line of code using substring method (or something else).

Help?

2
  • When a problem has very definitive answers such as this one it's always amusing to me watching how many different solutions the SO community provides. Commented Feb 22, 2010 at 19:36
  • One thing to note: the input string has a field called "Usernname". You then ask for the "UserName" field. Beware of casing when parsing strings. There are ways for dealing with this, of course. Commented Feb 22, 2010 at 19:42

9 Answers 9

15

For the sake of completeness, here is the Regex way of doing it. This will also work if the order changes.

// using System.Text.RegularExpressions;

string test1 = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";
string test2 = "FirstName=ABC;LastName=XZY;Password=1234;Username=User1";
string test3 = "FirstName=ABC;LastName=XZY;Password=1234";

string regexPattern = @"(?<=Username=)[^;\n]*";
var userName1 = Regex.Match(test1, regexPattern).Value; // User1
var userName2 = Regex.Match(test2, regexPattern).Value; // User1
var userName3 = Regex.Match(test3, regexPattern).Value; // string.Empty

// Compiling can speed up the Regex, at the expense of longer initial Initialization
// Use when this is called often, but measure.

Regex compiledRx = new Regex(regexPattern,RegexOptions.Compiled);
var userNameCompiled1 = compiledRx.Match(test1).Value; // User1
var userNameCompiled2 = compiledRx.Match(test2).Value; // User1
var userNameCompiled3 = compiledRx.Match(test3).Value; // string.Empty
Sign up to request clarification or add additional context in comments.

Comments

12

Looks like a delimited string, so this would work:

string result = myString.Split(';')[2].Split('=')[1];

However, if someone changes the value pair order, this will break.

There are better ways about this, that will not break if the order changes, the number of parameters is different etc - such as the Regular Expression as Michael posted, or the Linq queries posted by a number of people.

2 Comments

I appreciate that you were attempting to make it as short as possible, but I think we have the winner for the ugliest piece of code I've seen recently. (No offense intended!)
@user: I suggest you sign up with a real name - I'm beginning to recognize you by the digits in your user id. :-)
7

Here is an alternative solution (not too different from others, but which I think is more straightforward) which will work regardless of order.

var input = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";

Assert.AreEqual("User1", input
    .Split(';')
    .Select(item => item.Split('='))
    .Where(pair => pair[0].Equals("Username"))
    .Single()[1]);

2 Comments

Fails when there is no "Username" at the string.
If there might not be a username, you could add .Select(pair => pair[1]) before .Single() and change .Single() to .SingleOrDefault(). Then you just get null if there is no username.
4

This method will work even if the value-pairs are given in a different order. It splits on the semicolon, finds the item with "Username", then returns what's after the equal sign.

string theString = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";
string username = theString.Split(";").Where(s => s.Split("=")[0].Equals("Username")).ToArray()[0].Split("=")[1];

4 Comments

@Aaron: Sorry to ask, is syntax oke. I am getting error near .ToArray[0]..??
@user144842: You caught an error in my example! There are supposed to be parentheses after ToArray. I have updated my answer.
That would be half VB and half C# ... probably all off the top of his head.
Your suggestion is most suitable for me for now. Just Edit last [0] to [1] in your answer statment. Thanks.
4

Least number of lines of code is not always the best metric, but you could do what you need with Regex.

5 Comments

How odd, this is probably one of the first times I've ever seen a regex suggested and it be a valid answer. :p
Haven't you heard - Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. Jamie Zawinski
@Tanzelax: Regex becoming the new JQuery?
I like how this is an answer, i should go around telling everyone to use C# as my answer. I am sorry, but simply saying you could do what you need with Regex is not a valid answer. Supply a code example.
@Stan R: I am agree with you at least being new to programming...Sample Code helps a lot...
3

While the split answers are 'ok' if nothing ever changes, it's probably better to use a function because:

  • It makes your intentions clear.
  • It is easier to document.
  • It is easier to modify should the inevitable happen.
  • Works regardless of order.

(Even if you just put the one line split in the function! or at the very least add a comment to the split.)


static String GetUsername(String value)
{
    String result = "";
    String token = "Username=";

    int index = value.IndexOf(token) + token.Length;
    while (value[index] != ';')
    {
        result += value[index++];
        if (index > value.Length - 1)
            break;
    }

    return result;
}

2 Comments

I like the suggestion to encapsulate this "logic", but let's be evil: His sample didn't end in a ';'. Now imagine the "Username=" part is at the end, what would happen with your solution?
@Benjamin - While not difficult to handle that case; I think all solutions presented suffer from some deficiency. For example, what if there were two usernames in the string? What would happen? This solution would always pick the first. At any rate, I think this trivial problem has been taken to an extreme.
3

Not as simple as using split, however:

string input = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";
string username = Regex.Match(input, "Username=(?<username>.*?)(;|$)").Groups["username"].Value;

In this case, groups can be in any order.

And, if you like to get creative:

var answers = from tuple in input.Split(';')
              where tuple.StartsWith("Username=")
              select tuple.Split('=')[1];

username = answers.Count() > 0 ? answers.First() : string.Empty;

One might say the last piece has better semantics.

EDIT: Update the last piece to deal with input strings that doesn't have the required tuple.

2 Comments

Would fail if the source string is FirstName=ABC;Username=User1;LastName=XZY;Password=1234. Use the ? for a lazy search: Username=(?<username>.*?);
@Naeem Sarfraz: Thanks, you're right. Damn greedy thing. Also, I correted the case in which the Username is the last pair in the string. And now the REGEX is way complex...
1
        string t = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";
        string name = t.Split(';')[2].Split('=')[1];

Comments

1

This isn't the shortest... but probably one of the fastest.

string value = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";
int offset = value.IndexOf("Username=") + 9;
if (offset < 9)
    throw new Exception("Username= not found in string");
int len = value.IndexOf(';', offset) - offset;
if (len < 0)
    len = value.Length - offset;
string find = value.Substring(offset, len);

... the if (len < 0) is for is the Username is at the end of the string and doesn't end with a semicolon. If you want to ignore case you can replace the int offset line with this...

int offset = value.ToUpperInvariant().IndexOf("USERNAME=") + 9;

2 Comments

I know the "magic number" could be replaced by moving "Username=" to a variable such as token and using token.Length.
Feel free to complain about "Exception" I didn't feel like anything better for an example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.