Преобразование из инженерной записи в удвоение и REGEX, разбить строку на две части;цифры и символы - PullRequest
2 голосов
/ 22 ноября 2011

Я пытаюсь написать метод, который преобразует инженерную нотацию в double. Дело у меня сейчас очень особенное! Я имею в виду, что я не собираюсь искать такие силы, как "Мега, Гига и ...", я просто ищу плавающие точки.

Некоторые действительные примеры моего дела:

1.0 A должно быть 1

1.0064 mA или 1.0064 Ma должно быть 0.0010064 Обратите внимание, что я считаю M и m как мили ..., которые могут быть достигнуты используя метод ToLower(). и что A или a считается током для ампер.

У меня такой же случай для Напряжения, поэтому пользователь может вместо этого ввести V или v .

снова несколько действительных случаев: 256ma 366 m a 10.665 uA

Итак, в конце, прежде чем передать эту строку моему методу конвертации, я делаю text.ToLower().Remove(" ", string.Empty);, надеюсь, у меня останется простая строка для работы.

Теперь вторым шагом является разделение чисел из символов: 10.665ua должно привести к 10.665 и ua, поэтому я могу проверить первый символ ua по списку разрешенных строк и найти коэффициент мощности.

private List<string> AllowedCurrentStrings = new List<string>() { "a", "ma", "m", "ua", "u", "na", "n", "pa", "p" };

Так что я ищу твою помощь. сначала мне нужно знать, как разделить числа из символов, а затем сгруппировать символы в строку (или мне нужно сделать более позднюю?)

Или, если вы считаете, что мой подход не очень хорош, было бы неплохо услышать от вас лучший вариант!

Ответы [ 2 ]

2 голосов
/ 22 ноября 2011

Вы можете попробовать это:

    public double ConvertMeasure(string measure)
    {
        measure = measure.ToLower().Replace(" ", "");
        measure = measure.Substring(0, measure.Length - 1);
        char m = measure.Last();
        if (char.IsDigit(m))
            return double.Parse(measure, CultureInfo.InvariantCulture);

        double ret = double.Parse(measure.Substring(0, measure.Length - 1),
                                  CultureInfo.InvariantCulture);
        switch (m)
        {
            case 'm': return ret / 1E3;
            case 'u': return ret / 1E6;
            case 'n': return ret / 1E9;
            case 'p': return ret / 1E12;
        }
        return ret;
    }
1 голос
/ 22 ноября 2011

Хотя синтаксический разбор строк может быть немного быстрее, все это, безусловно, можно сделать с помощью регулярных выражений.Решение, использующее регулярное выражение для синтаксического анализа строки и словарь для выбора коэффициента преобразования, но которое по сути совпадает с ответом @Marco с некоторыми улучшениями в функциональном отношении, будет:

public double ConvertMeasure(string measure)
{
    var re = new Regex(@"(?i)(?<value>-?[\d.]+)\s*(?<multiplier>[munp]?)\s*(?<unit>[avw]*)");
    var conversionFactors = new Dictionary<string, double> {
    { "", 1 }, 
    { "m", 1E3 }, 
    { "u", 1E6 }, 
    { "n", 1E9 }, 
    { "p", 1E12 } };

    var m = re.Match(measure);

    double value = Convert.ToDouble(m.Groups["value"].Value);
    return value / conversionFactors[m.Groups["multiplier"].Value.ToLower()];
}

Это игнорируетрегистр строки и игнорирует пробел (включая вкладки, которые могут возникнуть, если кто-то будет вырезать и вставить значение вместо его ввода) между числом и множителем и единицей, но не игнорирует пробел внутри «числа»(то есть, 1.234 mA в порядке, но 1.2 34 mA не должно быть в порядке IMO, но анализируется как 1.234 с помощью решения @ Marco - просто будьте осторожны: D).Кроме того, он все равно будет работать, если кто-то случайно вставит перед номером дополнительные нечисловые символы, такие как = или окружающий набор скобок.

Конечно, ни одно из написанных решений не вернет фактическоеединица в любом случае.Я предполагаю, что, поскольку вы планировали разрешить «m», «u» и т. Д. (Без единицы измерения), у вас есть нечто похожее на текстовое поле с «Amps» или «Amperes» рядом с ним и вы хотите, чтобы кто-товведите любой из 1.3 1.3A, 1.3 u или 1.3 uA и т. д. Таким образом, вы знаете, что такое базовый блок - это решение обеспечит функциональность преобразования и проигнорирует фактический блок.

класс символов [avw] в регулярном выражении указывает, какие единицы разрешены (в данном случае a, v или w).Если вы хотите, чтобы кто-то случайно не поместил 1.234 mV в поле, которое ожидает Amps, вы можете изменить функцию, чтобы она принимала строковый параметр «AllowedUnits» (например, a или v), а затем вставьте этот параметр в регулярное выражение.вместо avw, таким образом:

    var re = new Regex(@"(?i)(?<value>-?[\d.]+)\s*(?<multiplier>[munp]?)\s*(?<unit>[" + AllowedUnits + @"]*)");

... затем передайте "a" в любое преобразование для ампер или "v" в любое преобразование для вольт и т. д.

Я не проверял это, но я думаю, что решение @ Marco сломается, если нет единицы (например, если строка имеет только m, u, n или p вместо mA, ua, nV и т. Д.).Я верю, что это урезает юнит, потому что обрезает последний символ.Если есть только один символ (например, u), он потеряет эти данные!Мое решение будет работать не только независимо от устройства, но даже если вы захотите позже поддерживать больше модулей, таких как Hz, mol или cd, хотя родинки и канделы могут быть не такими распространенными винженерный контекст ...

Удачи и веселья!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...