Парсинг отформатированной строки

GC.Collect вызова () вынуждает CLR сделать проход по стеку, чтобы видеть, может ли каждый объект быть истинно быть выпущенным путем проверки ссылок. Это будет влиять на масштабируемость, если количество объектов будет высоко, и, как также будет известно, инициирует сборку "мусора" слишком часто. Доверяйте CLR и позвольте сборщику "мусора" выполнить себя в надлежащих случаях.

15
задан Adrian Godong 11 September 2009 в 09:45
поделиться

6 ответов

Вы можете ' t unformat, потому что информация потеряна. String.Format - это «деструктивный» алгоритм, что означает, что вы не можете (всегда) вернуться назад.

Создайте новый класс, наследующий от string , куда вы добавляете член который отслеживает "{0} - {1}" и {"asdf", "qwer"} , переопределяет ToString () и немного измените свой код.

Если это станет слишком сложно, просто создайте тот же класс, но не наследуя от строки , и еще немного измените свой код.

ИМО,

10
ответ дан 1 December 2019 в 01:53
поделиться

Хотя комментарии о потерянной информации действительны, иногда вам просто нужно получить строковые значения строки с известным форматированием.

Один из способов - это это сообщение в блоге , написанное моим другом. Он реализовал метод расширения под названием string [] ParseExact () , похожий на DateTime.ParseExact () . Данные возвращаются в виде массива строк, но если вы можете смириться с этим, это очень удобно.

public static class StringExtensions
{
    public static string[] ParseExact(
        this string data, 
        string format)
    {
        return ParseExact(data, format, false);
    }

    public static string[] ParseExact(
        this string data, 
        string format, 
        bool ignoreCase)
    {
        string[] values;

        if (TryParseExact(data, format, out values, ignoreCase))
            return values;
        else
            throw new ArgumentException("Format not compatible with value.");
    }

    public static bool TryExtract(
        this string data, 
        string format, 
        out string[] values)
    {
        return TryParseExact(data, format, out values, false);
    }

    public static bool TryParseExact(
        this string data, 
        string format, 
        out string[] values, 
        bool ignoreCase)
    {
        int tokenCount = 0;
        format = Regex.Escape(format).Replace("\\{", "{");

        for (tokenCount = 0; ; tokenCount++)
        {
            string token = string.Format("{{{0}}}", tokenCount);
            if (!format.Contains(token)) break;
            format = format.Replace(token,
                string.Format("(?'group{0}'.*)", tokenCount));
        }

        RegexOptions options = 
            ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None;

        Match match = new Regex(format, options).Match(data);

        if (tokenCount != (match.Groups.Count - 1))
        {
            values = new string[] { };
            return false;
        }
        else
        {
            values = new string[tokenCount];
            for (int index = 0; index < tokenCount; index++)
                values[index] = 
                    match.Groups[string.Format("group{0}", index)].Value;
            return true;
        }
    }
}
16
ответ дан 1 December 2019 в 01:53
поделиться

Это просто невозможно в общем случае. Некоторая информация будет «потеряна» (границы строки) в методе Format . Предположим:

String.Format("{0}-{1}", "hello-world", "stack-overflow");

Как бы вы его «Неформатировали»?

3
ответ дан 1 December 2019 в 01:53
поделиться

После форматирования вы можете поместить полученную строку и массив объектов в словарь со строкой в ​​качестве ключа:

Dictionary<string,string []> unFormatLookup = new Dictionary<string,string []>
...
var arr = new string [] {"asdf", "qwer" };
var res = string.Format(format, arr);
unFormatLookup.Add(res,arr);

, а в методе Unformat вы можете просто передать строку и найти эту строку и верните используемый массив:

string [] Unformat(string res)
{
  string [] arr;
  unFormatLoopup.TryGetValue(res,out arr); //you can also check the return value of TryGetValue and throw an exception if the input string is not in.
  return arr; 
}
0
ответ дан 1 December 2019 в 01:53
поделиться

Предполагая, что «-» нет в исходных строках, можете ли вы просто не использовать Split?

var arr2 = formattedString.Split('-');

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

2
ответ дан 1 December 2019 в 01:53
поделиться

Простым решением может быть

  • замена всех токенов формата на (. *)
  • исключение всех других специальных символов в формате
  • сделать соответствие регулярного выражения не жадным

Это разрешит неясности до кратчайшего совпадения.

(Я плохо разбираюсь в RegEx, поправьте меня, ребята :))

1
ответ дан 1 December 2019 в 01:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: