简体   繁体   中英

Patterns for string manipulation (in C# or other languages)

I often find myself writing quite ugly code when doing string manipulations. The code does what's expected, but I would like to feel satisfied with how it looks as well as it performs. Are there any good books, websites, forums that addresses common string manipulation problems? And how would you code the following example scenarios?

A simple scenario: I have a collection of objects that I want to concatenate the result from a specific method on each object and separate each string with " AND ".

This code would do the trick, but it doesn't give that warm cozy feeling you would get after writing some piece of beautiful code.. ;).

List<MyClass> myColl = ..... // initialize the collection..
StringBuilder sb = new StringBuilder();
bool isFirst = true;
foreach (MyClass obj in myColl) {
    if (!isFirst) {
        sb.Append(" AND ");
    }
    isFirst = false;
    sb.Append(obj.MyStringBuildingMethod());
}

This would maybe be a nicer way if I would use lambda expressions:

List<MyClass> myColl = ..... // initialize the collection..
string result = String.Join(" AND ", myColl.Select(i => i.MyStringBuildingMethod()).ToArray());

And now a more complex scenario: I want to split a string on a delimiter and then split each part into a key/value. The value is enclosed in single quotes, and if the delimiter is inside the value, we should not split on that. The following code does what it should, but it feels like I have used duct tape or something.. ;)

string csvString = "name='Andersson, Per',country='Sweden',city='Stockholm'";
Dictionary<string, string> keyValues = new Dictionary<string, string>();

bool isInsideQuote = false;
int lastPosition = 0;
for (int i = 0; i < csvString.Length; i++) {
    if (csvString[i] == ',' && !isInsideQuote) {
        string[] keyValuePair = csvString.Substring(lastPosition, i - lastPosition).Split("=".ToCharArray(), 2);
        if (keyValuePair.Length == 2) {
            keyValues.Add(keyValuePair[0], keyValuePair[1].TrimStart("'".ToCharArray()).TrimEnd("'".ToCharArray()));
        }
        lastPosition = i + 1;
    }

    if (csvString[i] == '\'') {
        isInsideQuote = !isInsideQuote;
    }
}

string[] lastKeyValuePair = csvString.Substring(lastPosition).Split("=".ToCharArray(), 2);
if (lastKeyValuePair.Length == 2) {
    keyValues.Add(lastKeyValuePair[0], lastKeyValuePair[1].TrimStart("'".ToCharArray()).TrimEnd("'".ToCharArray()));
}

Your can use the String.Join(string delimiter, string[] words) method. In C# 3.0 syntax, this might look like the following:

var words = new string[] 
                      {
                         "this",
                         "that",
                         "the other"
                      };

var concatenatedResult = String.Join(" and ", words);

//should output "this and that and the other"
Console.WriteLine(concatenatedResult);

If you have a generic list and want to concatenate its values, you can do the following:

var words = new List<object>()
                    {
                      5,
                      DateTime.Now,
                      "something else"
                    };

var concatenatedResult = String.Join(" and ", words.Select(i => i.ToString()).ToArray());
//should output "5 and [system time] and something else"
Console.WriteLine(concatenatedResult);

Console.ReadLine();

Please note that the second example was ripped from another StackOverflow post: Convert List(of object) to List(of string) .

I've looked at the IL for the Join method, and it should be reasonably comparable in speed if not quicker than using the StringBuilder class. I wanted to ensure that instances of the String class were not being concatenated in code, which would have been very slow in comparison to the approach shown in the OP.

I would add an And for every record, and then simply strip the last And off at the end...

List<MyClass> myColl = ..... // initialize the collection..
StringBuilder sb = new StringBuilder();
foreach (MyClass obj in myColl)   
    sb.Append(obj.MyStringBuildingMethod() + " AND ");
string s = sb.ToString(0, sb.Length - 5);

I suppose this is slightly less convoluted than what you have for your second example, although it relies on the string being pretty strictly formatted. String parsing isn't always pretty.

string csvString = "name='Andersson, Per',country='Sweden',city='Stockholm'";

csvString = csvString.Replace("',", "'|");
string[] parts = csvString.Split('|');
foreach (string s in parts)  {
  string[] moreParts = s.Split('=');

  string key = moreParts[0];
  string value = moreParts[1].Trim("'"); 
  // do stuff?
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM