Метод C # regex.split добавляет пустую строку перед скобками - PullRequest
3 голосов
/ 08 июля 2011

У меня есть некоторый код, который токенизирует вход уравнения в массив строк:

string infix = "( 5 + 2 ) * 3 + 4";
string[] tokens = tokenizer(infix, @"([\+\-\*\(\)\^\\])");
foreach (string s in tokens)
{
   Console.WriteLine(s);
}

Теперь вот функция токенизатора:

public string[] tokenizer(string input, string splitExp)
        {
            string noWSpaceInput = Regex.Replace(input, @"\s", "");
            Console.WriteLine(noWSpaceInput);
            Regex RE = new Regex(splitExp);
            return (RE.Split(noWSpaceInput));
        }

Когда я запускаю это, все символы разделяются, но перед скобками в скобках вставляется пустая строка ... как мне удалить это?

// пустая строка здесь

(

5

+

2

// здесь пустая строка

) * * тысяча двадцать-один

*

3

+

4

Ответы [ 5 ]

3 голосов
/ 08 июля 2011

Я бы просто отфильтровал их:

public string[] tokenizer(string input, string splitExp)
{
    string noWSpaceInput = Regex.Replace(input, @"\s", "");
    Console.WriteLine(noWSpaceInput);
    Regex RE = new Regex(splitExp);
    return (RE.Split(noWSpaceInput)).Where(x => !string.IsNullOrEmpty(x)).ToArray();
}
2 голосов
/ 08 июля 2011

То, что вы видите, это то, что у вас нет ничего, кроме разделителя (то есть в начале строки (), а затем двух символов-разделителей рядом (т.е. )* в середине). Это по замыслу.

Как вы, возможно, обнаружили с String.Split, у этого метода есть необязательное перечисление, которое вы можете указать, чтобы оно удаляло все пустые записи, однако такого параметра с регулярными выражениями нет. В вашем конкретном случае вы можете просто проигнорировать любой токен длиной 0.

foreach (string s in tokens.Where(tt => tt.Length > 0))
{
   Console.WriteLine(s);
}
1 голос
/ 08 июля 2011

Ну, один из вариантов будет отфильтровать их потом:

return RE.Split(noWSpaceInput).Where(x => !string.IsNullOrEmpty(x)).ToArray();
1 голос
/ 08 июля 2011

Попробуйте (если вы не хотите фильтровать результат):

tokenizer(infix, @"(?=[-+*()^\\])|(?<=[-+*()^\\])");

Демонстрация Perl:

perl -E "say join ',', split /(?=[-+*()^])|(?<=[-+*()^])/, '(5+2)*3+4'"
(,5,+,2,),*,3,+,4

Хотя лучше использовать совпадение вместораскол в этом случае IMO.

0 голосов
/ 08 июля 2011

Я думаю, что вы можете использовать [StringSplitOptions.RemoveEmptyEntries] путем разделения

    static void Main(string[] args)
    {
        string infix = "( 5 + 2 ) * 3 + 4";
        string[] results = infix.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
        foreach (var result in results)
            Console.WriteLine(result);

        Console.ReadLine();
    }
...