字符串操作的模式(使用C#或其他语言)

时间:2009-09-09 21:45:34

标签: c# string design-patterns

我经常发现自己在进行字符串操作时编写了非常难看的代码。代码完成了预期的工作,但我希望对它的外观和执行情况感到满意。是否有任何好的书籍,网站,论坛解决常见的字符串操作问题?您将如何编写以下示例场景?

一个简单的场景:我有一组对象,我希望将每个对象上的特定方法的结果连接起来,并用“AND”分​​隔每个字符串。

这段代码可以解决这个问题,但是在编写一些漂亮的代码之后,它不会给你温暖舒适的感觉..;)。

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());
}

如果我使用lambda表达式,这可能是一个更好的方法:

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

现在是一个更复杂的场景:我想在分隔符上拆分一个字符串,然后将每个部分拆分成一个键/值。该值用单引号括起来,如果分隔符在值内,我们不应该拆分它。下面的代码做了它应该做的事情,但感觉就像我使用了胶带或其他东西..;)

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()));
}

3 个答案:

答案 0 :(得分:4)

您可以使用String.Join(string delimiter, string[] words)方法。在C#3.0语法中,这可能如下所示:

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);

如果您有通用列表并希望连接其值,则可以执行以下操作:

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();

请注意,第二个示例是从另一个StackOverflow帖子中删除的:Convert List(of object) to List(of string)

我已经查看了IL的Join方法,如果不比使用StringBuilder类快,它应该在速度上具有合理的可比性。我想确保String类的实例没有在代码中连接,与OP中显示的方法相比,这将非常慢。

答案 1 :(得分:2)

我会为每条记录添加一个And,然后在最后删除最后一个And off ...

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);

答案 2 :(得分:0)

我认为这比你的第二个例子略微复杂,尽管它依赖于非常严格格式化的字符串。字符串解析并不总是很好。

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?
}