C # функция для преобразования ввода текста в футах / дюймах / метрах / сантиметрах / миллиметрах в числовые значения - PullRequest
4 голосов
/ 28 мая 2011

Я пишу функцию для получения сокращенных значений и преобразования их в стандартизированный числовой формат.Существует ли какой-либо стандартный код, который бы выполнял «наилучшее возможное» преобразование текста произвольного измерения и превращал бы его в числовые измерения, если текст действителен?

Я думаю, что я ищу что-то вроде bool TryParseMeasurement (strings, вне десятичной d).Кто-нибудь знает о такой функции?

Вот пример некоторых входных значений, которые я видел:

Imperial

  • 6 дюймов
  • 6 дюймов
  • 6 ”
  • 4 фута 2 дюйма
  • 4'2”
  • 4 '2 ”
  • 3 фута
  • 3 '
  • 3'
  • 3 фута
  • 3 фута 10 дюймов
  • 3 фута 13 дюймов (следует преобразовать в 4'1 ”)

Метрика

  • 1,2м
  • 1,332м
  • 1 метр
  • 481мм

Ответы [ 3 ]

6 голосов
/ 28 мая 2011

Вот некоторый код, который мы написали в приложении довольно давно, где мы делали нечто подобное.Это не самое лучшее, но вы можете адаптироваться или получить какую-то точку отсчета.

public static class UnitConversion
{
    public static string[] lstFootUnits = new string[] {"foots", "foot", "feets", "feet", "ft", "f", "\""};
    public static string sFootUnit = "ft";

    public static string[] lstInchUnits = new string[] { "inches", "inchs", "inch", "in", "i", "\'" };
    public static string sInchUnit = "in";

    public static string[] lstPoundUnits = new string[] { "pounds", "pound", "pnds", "pnd", "lbs", "lb", "l", "p" };
    public static string sPoundUnit = "lbs";

    public static string[] lstOunceUnits = new string[] { "ounces", "ounce", "ozs", "oz", "o" };
    public static string sOunceUnit = "oz";

    public static string[] lstCentimeterUnits = new string[] { "centimeters", "centimeter", "centimetres", "centimetre", "cms", "cm", "c"};
    public static string sCentimeterUnit = "cm";

    public static string[] lstKilogramUnits = new string[] { "kilograms", "kilogram", "kilos", "kilo", "kgs", "kg", "k" };
    public static string sKilogramsUnit = "kgs";

    /// <summary>
    /// Attempt to convert between feet/inches and cm
    /// </summary>
    /// <param name="sHeight"></param>
    /// <returns></returns>
    public static string ConvertHeight(string sHeight)
    {
        if (!String.IsNullOrEmpty(sHeight))
        {
            sHeight = UnitConversion.CleanHeight(sHeight);

            if (sHeight.Contains(UnitConversion.sFootUnit))
            {
                sHeight = sHeight.Replace(UnitConversion.sFootUnit, "|");
                sHeight = sHeight.Replace(UnitConversion.sInchUnit, "|");

                string[] sParts = sHeight.Split('|');

                double? dFeet = null;
                double? dInches = null;
                double dFeetParsed;
                double dInchesParsed;

                if (sParts.Length >= 2 && double.TryParse(sParts[0].Trim(), out dFeetParsed))
                {
                    dFeet = dFeetParsed;
                }
                if (sParts.Length >= 4 && double.TryParse(sParts[2].Trim(), out dInchesParsed))
                {
                    dInches = dInchesParsed;
                };

                sHeight = UnitConversion.FtToCm(UnitConversion.CalculateFt(dFeet ?? 0, dInches ?? 0)).ToString() + " " + UnitConversion.sCentimeterUnit;
            }
            else if (sHeight.Contains(UnitConversion.sCentimeterUnit))
            {
                sHeight = sHeight.Replace(UnitConversion.sCentimeterUnit, "|");
                string[] sParts = sHeight.Split('|');

                double? dCentimeters = null;
                double dCentimetersParsed;

                if (sParts.Length >= 2 && double.TryParse(sParts[0].Trim(), out dCentimetersParsed))
                {
                    dCentimeters = dCentimetersParsed;
                }

                int? iFeet;
                int? iInches;
                if (UnitConversion.CmToFt(dCentimeters, out iFeet, out iInches))
                {
                    sHeight = (iFeet != null) ? iFeet.ToString() + " " + UnitConversion.sFootUnit : "";
                    sHeight += (iInches != null) ? " " + iInches.ToString() + " " + UnitConversion.sInchUnit : "";
                    sHeight = sHeight.Trim();
                }
                else
                {
                    sHeight = "";
                }
            }
            else
            {
                sHeight = "";
            }
        }
        else
        {
            sHeight = "";
        }

        return sHeight;
    }

    /// <summary>
    /// Attempt to convert between Kgs and Lbs
    /// </summary>
    /// <param name="sWeight"></param>
    /// <returns></returns>
    public static string ConvertWeight(string sWeight)
    {
        if (!String.IsNullOrEmpty(sWeight))
        {
            sWeight = UnitConversion.CleanWeight(sWeight);

            if (sWeight.Contains(UnitConversion.sKilogramsUnit))
            {
                sWeight = sWeight.Replace(UnitConversion.sKilogramsUnit, "|");

                string[] sParts = sWeight.Split('|');

                double? dKilograms = null;
                double dKilogramsParsed;

                if (sParts.Length >= 2 && double.TryParse(sParts[0].Trim(), out dKilogramsParsed))
                {
                    dKilograms = dKilogramsParsed;
                }

                sWeight = UnitConversion.KgToLbs(dKilograms).ToString("#.###") + " " + UnitConversion.sPoundUnit;
            }
            else if (sWeight.Contains(UnitConversion.sPoundUnit))
            {
                sWeight = sWeight.Replace(UnitConversion.sPoundUnit, "|");

                string[] sParts = sWeight.Split('|');

                double? dPounds = null;
                double dPoundsParsed;

                if (sParts.Length >= 2 && double.TryParse(sParts[0].Trim(), out dPoundsParsed))
                {
                    dPounds = dPoundsParsed;
                }

                sWeight = UnitConversion.LbsToKg(dPounds).ToString("#.###") + " " + UnitConversion.sKilogramsUnit;
            }
            else
            {
                sWeight = "";
            }
        }
        else
        {
            sWeight = "";
        }

        return sWeight;
    }

    public static double? CalculateFt(double dFt, double dInch)
    {
        double? dFeet = null;
        if (dFt >= 0 && dInch >= 0 && dInch <= 12)
        {
            dFeet = dFt + (dInch / 12);
        }
        return dFeet;
    }

    public static double KgToLbs(double? dKg)
    {
        if (dKg == null)
        {
            return 0;
        }
        return dKg.Value * 2.20462262;
    }

    public static double LbsToKg(double? dLbs)
    {
        if (dLbs == null)
        {
            return 0;
        }
        return dLbs.Value / 2.20462262;
    }

    public static double FtToCm(double? dFt)
    {
        if (dFt == null)
        {
            return 0;
        }
        return dFt.Value * 30.48;
    }

    public static bool CmToFt(double? dCm, out int? iFt, out int? iInch)
    {

        if (dCm == null)
        {
            iFt = null;
            iInch = null;
            return false;
        }

        double dCalcFeet = dCm.Value / 30.48;
        double dCalcInches = dCalcFeet - Math.Floor(dCalcFeet);
        dCalcFeet = Math.Floor(dCalcFeet);
        dCalcInches = dCalcInches * 12;

        iFt = (int)dCalcFeet;
        iInch = (int)dCalcInches;
        return true;
    }

    private static string CleanUnit(string sOriginal, string[] lstReplaceUnits, string sReplaceWithUnit)
    {
        System.Text.StringBuilder sbPattern = new System.Text.StringBuilder();

        foreach (string sReplace in lstReplaceUnits)
        {
            if (sbPattern.Length > 0)
            {
                sbPattern.Append("|");
            }
            sbPattern.Append(sReplace);
        }
        sbPattern.Insert(0,@"(^|\s)(");
        sbPattern.Append(@")(\s|$)");


        System.Text.RegularExpressions.Regex rReplace = new System.Text.RegularExpressions.Regex(sbPattern.ToString(), System.Text.RegularExpressions.RegexOptions.IgnoreCase);

        sOriginal = rReplace.Replace(sOriginal, sReplaceWithUnit);

        /*foreach (string sReplace in lstReplaceUnits)
        {

            sOriginal = sOriginal.Replace(sReplace, " " + sReplaceWithUnit);
        }*/


        return sOriginal;
    }

    private static bool StringHasNumbers(string sText)
    {
        System.Text.RegularExpressions.Regex rxNumbers = new System.Text.RegularExpressions.Regex("[0-9]+");

        return rxNumbers.IsMatch(sText);
    }

    private static string ReduceSpaces(string sText)
    {
        while (sText.Contains("  "))
        {
            sText = sText.Replace("  ", " ");
        }

        return sText;
    }

    private static string SeperateNumbers(string sText)
    {
        bool bNumber = false;
        if (!String.IsNullOrEmpty(sText))
        {
            for (int iChar = 0; iChar < sText.Length; iChar++)
            {
                bool bIsNumber = (sText[iChar] >= '0' && sText[iChar] <= '9') || 
                    (sText[iChar] == '.' && iChar < sText.Length - 1 && sText[iChar + 1] >= '0' && sText[iChar + 1] <= '9');

                if (iChar > 0 && bIsNumber != bNumber)
                {
                    sText = sText.Insert(iChar, " ");
                    iChar++;
                }

                bNumber = bIsNumber;
            }
        }

        return sText;
    }

    public static string CleanHeight(string sHeight)
    {
        if (UnitConversion.StringHasNumbers(sHeight))
        {
            sHeight = SeperateNumbers(sHeight);
            sHeight = CleanUnit(sHeight, UnitConversion.lstFootUnits, UnitConversion.sFootUnit);
            sHeight = CleanUnit(sHeight, UnitConversion.lstInchUnits, UnitConversion.sInchUnit);
            sHeight = CleanUnit(sHeight, UnitConversion.lstCentimeterUnits, UnitConversion.sCentimeterUnit);
            sHeight = SeperateNumbers(sHeight);
            sHeight = ReduceSpaces(sHeight);
        }
        else
        {
            sHeight = "";
        }

        return sHeight;
    }

    public static string CleanWeight(string sWeight)
    {
        if (UnitConversion.StringHasNumbers(sWeight))
        {
            sWeight = SeperateNumbers(sWeight);
            sWeight = CleanUnit(sWeight, UnitConversion.lstOunceUnits, UnitConversion.sOunceUnit);
            sWeight = CleanUnit(sWeight, UnitConversion.lstPoundUnits, UnitConversion.sPoundUnit);
            sWeight = CleanUnit(sWeight, UnitConversion.lstKilogramUnits, UnitConversion.sKilogramsUnit);
            sWeight = SeperateNumbers(sWeight);
            sWeight = ReduceSpaces(sWeight);
        }
        else
        {
            sWeight = "";
        }

        return sWeight;
    }
}
4 голосов
/ 29 мая 2011

Это должно помочь вам создать метод расширения строки для этой цели. Когда вы создаете метод расширения, вы присоединяете новый вызов функции к существующему классу. В этом мы собираемся присоединить метод к классу 'string', который возвращает значение типа double, как число миллиметров в данном имперском значении, ПРЕДОСТАВЛЯЯ, что значение может быть проанализировано на основе предоставленных вами примеров.

using System;
using System.Text;

namespace SO_Console_test
{
    static class ConversionStringExtensions
    {
        //this is going to be a simple example you can 
        //fancy it up a lot...
        public static double ImperialToMetric(this string val)
        {
            /*
             * With these inputst we want to total inches.
             * to do this we want to standardize the feet designator to 'f' 
             * and remove the inch designator altogether.
                6 inches
                6in
                6”
                4 feet 2 inches
                4’2”
                4 ‘ 2 “
                3 feet
                3’
                3 ‘
                3ft
                3ft10in
                3ft 13in (should convert to 4’1”) ...no, should convert to 49 inches, then to metric.
             */

            //make the input lower case and remove blanks:
            val = val.ToLower().Replace(" ", string.Empty);

            //make all of the 'normal' feet designators to "ft"
            string S = val.Replace("\'", "f").Replace("feet", "f").Replace("ft", "f").Replace("foot", "f").Replace("‘", "f").Replace("’", "f");

            //and remove any inch designator
            S = S.Replace("\"", string.Empty).Replace("inches", string.Empty).Replace("inch", string.Empty).Replace("in", string.Empty).Replace("“", string.Empty).Replace("”", string.Empty);

            //finally we have to be certain we have a number of feet, even if that number is zero
            S = S.IndexOf('f') > 0 ? S : "0f" + S;

            //now, any of the inputs above will have been converted to a string 
            //that looks like 4 feet 2 inches => 4f2

            string[] values = S.Split('f'); 

            int inches = 0;
            //as long as this produces one or two values we are 'on track' 
            if (values.Length < 3)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    inches += values[i] != null && values[i] != string.Empty ? int.Parse(values[i]) * (i == 0 ? 12 : 1) : 0 ;
                }
            }

            //now inches = total number of inches in the input string.

            double result = inches * 25.4;

            return result;

        }
    }
}

При этом «ImperialToMetric ()» становится методом любой строки и может вызываться в любом месте, на которое ссылается расширение, содержащее класс ConversionStringExtensions. Вы можете использовать его как:

namespace SO_Console_test
{
    class Program
    {
        static void Main(string[] args)
        {    
            showConversion();
            Console.ReadLine();

        }

        private static void showConversion()
        {
            //simple start:
            Console.WriteLine("6ft 2\"".ImperialToMetric().ToString() + " mm");

            //more robust:
            var Imperials = new List<string>(){"6 inches",
                "6in",
                "6”",
                "4 feet 2 inches",
                "4’2”",
                "4 ‘ 2 “",
                "3 feet",
                "3’",
                "3 ‘",
                "3ft",
                "3ft10in",
                "3ft 13in"};

            foreach (string imperial in Imperials)
            {
                Console.WriteLine(imperial + " converted to " + imperial.ImperialToMetric() + " millimeters");
            }


        }
}

Очевидно, что на данный момент звонок на "Fred".ImperialToMetric не будет играть хорошо. Вам понадобится обработка ошибок и, возможно, некоторые варианты поворота 1234 мм, 1,234 км и т. Д., Но как только вы удалите это, у вас есть метод, который вы можете использовать везде, где захотите.

1 голос
/ 23 февраля 2014
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            double km,m,f,i,cm;

            Console.WriteLine("The distance between karachi and lahore in (kilometer)km is=");
            km = Convert.ToInt32(Console.ReadLine());

            m = km * 1000;
            Console.WriteLine("The distance between karachi and lahore in meter(m) is="+m);

            f = km * 3280.84;
            Console.WriteLine("The distance between karachi and lahore in feet(f) is="+f);

            i = km * 39370.1;
            Console.WriteLine("The distance between karachi and lahore in inches(i) is="+i);

            cm = m * 100;
            Console.WriteLine("The distance between karachi and lahore in centimeter(cm) is="+cm);

            Console.ReadLine();
        }
    }
}
...