C#将字符串拆分为标记的更直观的方法是什么?

时间:2015-08-12 21:20:55

标签: c# string token

我有一个方法,它接受一个包含各种字符的字符串,但我只关注下划线'_'和美元符号'$'。我希望通过下划线将字符串拆分为令牌,因为下划线包含重要信息。

但是,如果$包含在下划线之间的区域中,那么应该从最后一次下划线到结尾创建一个标记(忽略最后一节中的任何下划线)。

示例

输入:Hello_To_The $ Great_World

预期的代币:你好,To,$ Great_World

问题

下面我有一个解决方案,但我想知道是否有比我下面更清晰/更直观的方式?

var aTokens = new List<string>();
var aPos = 0;
for (var aNum = 0; aNum < item.Length; aNum++)
{
    if (aNum == item.Length - 1)
    {
        aTokens.Add(item.Substring(aPos, item.Length - aPos));
        break;
    }               
    if (item[aNum] == '$')
    {
        aTokens.Add(item.Substring(aPos, item.Length - aPos));
        break;
    }
    if (item[aNum] == '_')
    {
    aTokens.Add(item.Substring(aPos, aNum - aPos));
    aPos = aNum + 1;
    }
}

3 个答案:

答案 0 :(得分:2)

您可以按_分割字符串,而不是$

为此您可以使用以下正则表达式:

(?<!\$.*)_

示例代码:

string input = "Hello_To_The$Great_World";
string[] output = Regex.Split(input, @"(?<!\$.*)_");

你也可以在没有正则表达式且没有循环的情况下完成任务,但是在2次拆分的帮助下:

string input = "Hello_To_The$Great_World";
string[] temp = input.Split(new[] { '$' }, 2);
string[] output = temp[0].Split('_');
if (temp.Length > 1)
    output[output.Length - 1] = output[output.Length - 1] + "$" + temp[1];

答案 1 :(得分:1)

此方法效率不高或干净,但它可以让您大致了解如何执行此操作:

  1. 将您的字符串拆分为令牌
  2. 查找包含$
  3. 的第一个字符串的索引
  4. 返回一个包含前n个令牌的新数组,最后一个令牌是连接的其余字符串。
  5. 利用IEnumerable或者通过for循环而不是所有这些Array.Copy的东西可能更有用......但是你得到了它的要点。

    private string[] SomeMethod(string arg)
    {
        var strings = arg.Split(new[] { '_' });
    
        var indexedValue = strings.Select((v, i) => new { Value = v, Index = i }).FirstOrDefault(x => x.Value.Contains("$"));
    
        if (indexedValue != null)
        {
            var count = indexedValue.Index + 1;
    
            string[] final = new string[count];
            Array.Copy(strings, 0, final, 0, indexedValue.Index);
            final[indexedValue.Index] = String.Join("_", strings, indexedValue.Index, strings.Length - indexedValue.Index);
            return final;
        }
    
        return strings;
    }
    

答案 2 :(得分:1)

这是我的版本(循环所以去年......)

const char dollar = '$';
const char underscore = '_';

var item = "Hello_To_The$Great_World";
var aTokens = new List<string>();

int dollarIndex = item.IndexOf(dollar);
if (dollarIndex >= 0)
{
    int lastUnderscoreIndex = item.LastIndexOf(underscore, dollarIndex);
    if (lastUnderscoreIndex >= 0)
    {
        aTokens.AddRange(item.Substring(0, lastUnderscoreIndex).Split(underscore));
        aTokens.Add(item.Substring(lastUnderscoreIndex + 1));
    }
    else
    {
        aTokens.Add(item);
    }
}
else
{
    aTokens.AddRange(item.Split(underscore));
}

修改:

我应该添加,更清晰/更直观是非常主观的,因为你已经通过提供的各种答案找到了。从可维护性的角度来看,编写解析方法的单元测试更为重要!

测试此处发布的各种方法的性能也是一项有趣的练习 - 很快就会发现原始版本比使用正则表达式要快得多! (虽然在现实生活中,这种方法的性能可能不会对你的应用产生任何影响!)