Split strings in the best elegant way of the form x:y>z to get z

时间:2015-06-15 14:22:13

标签: c#

I have some values as

"name1:password1=>role1,name2:password2=>role2,name3:password3=>role3"

The thing is that, I need to check if the name and password is corectly matched or not (these values will be passed at runtime). If matched then I need to pick up the role.

My current implementation is

public string IsAuthenticUser(string userId, string password)
    {
        var IsauthenticUsers = System.Configuration.ConfigurationManager.AppSettings["authenticUsers"]
            .Split(',')
            .ToList()
            .Exists(a => a == userId + ":" + password);

       // some other splitting code ...etc....

    }

I can again split by ('=>') and can get it done by some way.

Is there any elegant way (I am sure there will be ..may be with RegEX) to do this?

6 个答案:

答案 0 :(得分:0)

If you pad the settings with comma's, the string you need to search for is always ",user:password=>". I'm sure there's a Regex guru who can give a one-line answer, but this should work as well (assuming there are no special characters in the usernames, passwords and roles):

var settings = "," + System.Configuration.ConfigurationManager.AppSettings["authenticUsers"] + ",";
var needle = "," + userId + ":" + password + "=>";
var index = settings.IndexOf(needle);
if (index != -1) {
    var roleIndex = index + needle.Length;
    var nextCommaIndex = settings.IndexOf(",", roleIndex);
    var role = settings.Substring(roleIndex, nextCommaIndex - roleIndex - 1);
}

答案 1 :(得分:0)

If you're interested in a Regex method of obtaining your information, you can try the following:

string data = "name1:password1=>role1,name2:password2=>role2,name3:password3=>role3";
Match match = Regex.Match(data, "(?<un>\\w+):(?<pw>\\w+)=>(?<role>\\w+)");
while (match.Success)
{
    Console.WriteLine(String.Format("{0} {1} {2}", match.Groups["un"], match.Groups["pw"], match.Groups["role"]));
    match = match.NextMatch();
}

Results:

name1 password1 role1
name2 password2 role2
name3 password3 role3

答案 2 :(得分:0)

Parsing the string ahead of time will save you a lot of work at runtime.

You could make a Dictionary<Tuple<string,string>,string> where the tuple is a (username,password) pair, and the string to which it maps is the role.

You can do the preprocessing like this:

private static KeyValuePair<Tuple<string,string>,string> ParseRole(string s) {
    int pos1 = s.IndexOf(':');
    int pos2 = s.IndexOf("=>", pos1+1);
    if (pos1 < 0 || pos2 < 0) {
        throw new ArgumentException();
    }
    return new KeyValuePair<Tuple<string,string>,string>(
        Tuple.Create(
            s.Substring(0, pos1)
        ,   s.Substring(pos1+1, pos2-pos1-1)
        )
    ,   s.Substring(pos2+2)
    );
}
...
Dictionary<Tuple<string,string>,string> userRoles = BigString
    .Split(',')
    .Select(s=>ParseRole(s))
    .ToDictionary(p => p.Key, p => p.Value);

With this dictionary in hand you can retrieve roles in a single lookup:

string role;
if (!userRoles.TryGetValue(Tuple.Creare(userName, Password), out role)) {
    Console.WriteLine("Role not found");
    return null;
}
return role;

Demo.

答案 3 :(得分:0)

I would split on => as you've already considered. You could use this query:

public string IsAuthenticUser(string userId, string password)
{
    return System.Configuration.ConfigurationManager.AppSettings["authenticUsers"]
        .Split(',')
        .Select(token => token.Split(new[]{"=>"},StringSplitOptions.None))
        .Select(arr => new {  
            Username = arr[0].Split(':')[0], 
            Password = arr[0].Split(':').Last(), 
            Role     = arr.Last()
        })
        .Where(x => x.Username == userId && x.Password == password)
        .Select(x => x.Role)
        .DefaultIfEmpty(null)
        .First();
}

答案 4 :(得分:0)

Assuming the string isn't massive enough for this to cause performance issues and you don't mind the inefficiency of redoing the same split multiple times i'd do it like this for readability :

public string IsAuthenticUser(string userId, string password)
{
    var AuthenticUsers = System.Configuration.ConfigurationManager.AppSettings["authenticUsers"];


    return AuthenticUsers 
        .Split(',')
        .Select(user=> new
        {
            login = user.Split(':').First(),
            password = user.Split(':').Last().Split('=').First(),
            role = user.Split(':').Last().Split('>').Last(),
        })
        .Any(user=>user.login == userId && user.password == password);
}

答案 5 :(得分:0)

public string IsAuthenticUser(string userId, string password)
{
    string userPass = string.Format("{0}:{1}", userId, password);
    string[] tokens = System.Configuration.ConfigurationManager.AppSettings["authenticUsers"]
                            .Split(new string[] {",", "=>"}, StringSplitOptions.RemoveEmptyEntries);
    for (int i = 0; i < tokens.Length; i += 2)
    {
        if (tokens[i] == userPass)
        {
            return tokens[i + 1];
        }
    }
    return null; // no match.
}