C #: Как мне преобразовать следующее? - PullRequest
1 голос
/ 11 февраля 2010

Используя C #, как бы вы конвертировали String, который также содержит символы новой строки и табуляции (4 пробела) из следующего формата

A {
   B {
      C = D
      E = F
   }
   G = H
}

в следующие

A.B.C = D
A.B.E = F
A.G = H

Обратите внимание, что от A до H являются просто заполнителями для значений String, которые не будут содержать символы '{', '}' и '='. Выше приведен только пример, и фактическое String для преобразования может содержать вложенность значений, которая является бесконечно глубокой, а также может содержать бесконечное число «? =?».

Ответы [ 4 ]

6 голосов
/ 11 февраля 2010

Возможно, вы захотите разобрать это, а затем сгенерировать желаемый формат. Попытка выполнить преобразование регулярных выражений ни к чему вас не приведет.

Токенизируйте строку, затем пройдите через токены и создайте синтаксическое дерево. Затем пройдитесь по дереву, генерирующему результат.

В качестве альтернативы, поместите каждое «пространство имен» в стек, когда вы его встречаете, и вытолкните его, когда вы встретите закрывающую скобку.

2 голосов
/ 11 февраля 2010

Не очень красиво, но вот реализация, которая использует стек:

static string Rewrite(string input)
{
    var builder = new StringBuilder();
    var stack = new Stack<string>();
    string[] lines = input.Split('\n');
    foreach (var s in lines)
    {
        if (s.Contains("{") || s.Contains("="))
        {
            stack.Push(s.Replace("{", String.Empty).Trim());
        }
        if (s.Contains("="))
        {
            builder.Append(string.Join(".", stack.Reverse().ToArray()));
            builder.Append(Environment.NewLine);
        }
        if (s.Contains("}") || s.Contains("="))
        {
            stack.Pop();
        }
   }
   return builder.ToString();
}
1 голос
/ 11 февраля 2010

Вы можете делать это с помощью регулярных выражений, это просто не самый эффективный способ сделать это, так как вам нужно сканировать строку несколько раз.

while (s.Contains("{")) {
    s = Regex.Replace(s, @"([^\s{}]+)\s*\{([^{}]+)\}", match => {
        return Regex.Replace(match.Groups[2].Value,
                             @"\s*(.*\n)",
                             match.Groups[1].Value + ".$1");
    });
}

Результат:

A.B.C = D
A.B.E = F
A.G = H

Я все еще думаю, что использование парсера и / или стекового подхода - лучший способ сделать это, но я просто подумал, что предложу альтернативу.

1 голос
/ 11 февраля 2010

Псевдокод для стекового метода:

function do_processing(Stack stack)
    add this namespace to the stack;
    for each sub namespace of the current namespace
        do_processing(sub namespace)
    end
    for each variable declaration in the current namespace
        make_variable_declaration(stack, variable declaration)
    end
end
...