5

我正在编写一个函数来获取速记值并将它们转换为标准化的数字格式。是否有任何标准代码可以对任意测量文本进行“最佳”转换,并在文本有效的情况下将其转换为数字测量?

我想我正在寻找类似 bool TryParseMeasurement(string s, out decimal d) 的东西。有谁知道这样的功能?

这是我见过的一些输入值的示例:

帝国

  • 6英寸
  • 6英寸
  • 6”</li>
  • 4英尺2英寸
  • 4'2”</li>
  • 4’ 2”</li>
  • 3 英尺
  • 3'</li>
  • 3'</li>
  • 3英尺
  • 3英尺10英寸
  • 3 英尺 13 英寸(应转换为 4 英尺 1 英寸)

公制

  • 1m
  • 1.2m
  • 1.321m
  • 1米
  • 481毫米
4

4 回答 4

7

这是我们很久以前在应用程序中编写的一些代码,我们在那里做类似的事情。这不是最好的,但你可能能够适应,或者得到某种起点。

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;
    }
}
于 2011-05-27T22:23:00.603 回答
4

为此目的构建字符串的扩展方法应该会为您提供很好的服务。当你构建一个扩展方法时,你将一个新的函数调用附加到一个现有的类。在此,我们将向“字符串”类附加一个方法,该方法返回一个双精度值,作为给定英制值的毫米数,前提是可以根据您提供的示例解析该值。

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");
            }


        }
}

显然,此时调用 to"Fred".ImperialToMetric不会很好。您将需要进行错误处理,并且可能需要一些选项来将 1234 毫米转向 1.234 公里等,但是一旦您将其清除,您就有一种方法可以在您选择的任何地方使用。

于 2011-05-28T20:37:51.227 回答
0
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();
        }
    }
}
于 2014-02-23T18:45:27.897 回答
0

我写的字符串的扩展只是为了发现这里已经有一个解决方案:) 唯一剩下要做的就是将“feet”、“ft”、“'”替换为“'”和“inches”、“英寸"、"英寸"、"""、"\"" 到 "''"。

using System;

namespace CustomExtensions
{
    public static class StringExtension
    {
        const float mPerFeet = 30.48f / 100;
        const float mPerInch = 2.54f / 100;

        // input options:
        // 5'
        // 5'6''
        // 18''
        // 24''
        // 5'6
        // 5 ' 6 ''
        // 5' 6''
        // corner cases:
        // '' will return 0
        // 5''6'' will interpret as 5'6''
        // 5'6' will interpret as 5'6''
        // 6 will interpret as 6''
        // 6''' will interpret as 6''
        public static float MetersFromFeetInches(this string feetInches)
        {
            float feet = 0;
            float inches = 0;
            string[] separators = new string[] { "'", "''", " " };
            string[] subs = feetInches.Split(separators, StringSplitOptions.RemoveEmptyEntries);
            if (subs.Length == 1)
            {
                if (feetInches.Trim().EndsWith("''"))
                {
                    float.TryParse(subs[0], out inches);
                }
                else if (!feetInches.Trim().EndsWith("''") && !feetInches.Trim().EndsWith("'"))
                {
                    float.TryParse(subs[0], out inches);
                }
                else
                {
                    float.TryParse(subs[0], out feet);
                }
            }
            else if (subs.Length > 1)
            {
                float.TryParse(subs[0], out feet);
                float.TryParse(subs[1], out inches);
            }
            return feet * mPerFeet + inches * mPerInch;
        }
    }
}
于 2021-07-28T08:33:58.317 回答