有没有任何C#库提供与谷歌在输入查询时所做的相同功能,例如“13英里743码(米)”,它将返回“21 600米”(例如)。
我想要做的是给函数字符串部分13 miles 743 yards
,然后以米为单位向后吐出一个int / double。它需要能够处理所有单位输入类型(公里/米/弗隆/英里/码/ ...),但输出只需要以米为单位。
编写自己的文件并不难,但只要有一个经过测试的库就可以了。
答案 0 :(得分:3)
我找不到任何答案,所以我建立了自己的:)这里唯一真正的“魔法”是Regex表达式,用于从原始字符串中获取值/单位组。从那里,它是简单的分数/数字解析,然后计算每个单位代表多少米。我没有测试过这么多,所以如果你发现了改进或错误,请告诉我(下面的代码在无法处理的情况下应该抛出异常)。
它不会处理愚蠢的用户输入,但是如果每个部分的格式为“[number] [unit]”,我认为它应该可以正常工作。如果输入不符合(例如,12/32/43
或1.43.3.2.44
作为值),则无法假设。我认为它会在句子中处理额外的松散,例如1 kilometer and 10 miles
(将删除and
)。如果您知道完整的单位清单,我没有添加任何可能的单位。相当于我想知道它的相当于米。
以下是几项测试,
var a = ExtractDistance("1 1/16 Miles 3/4 yards");
var b = ExtractDistance("02234890234.853 meters");
var c = ExtractDistance("1.8 miles 3.2 furlong");
var d = ExtractDistance("1 kilometer");
var e = ExtractDistance("1/16 Miles");
这是我的代码:
private static Dictionary<string, double> _DistanceLookup = new Dictionary<string, double>()
{
{"mile", 1609.344},
{"furlong", 201.168},
{"yard", 0.9144},
{"inch", 0.0254},
{"foot", 0.3048},
{"feet", 0.3048},
{"kilometer", 1000},
{"kilometre", 1000},
{"metre", 1},
{"meter", 1},
{"centimeter", 0.01},
{"centimetre", 0.01},
{"millimeter", 0.001},
{"millimetre", 0.001},
};
private static double ConvertFraction(string fraction)
{
double value = 0;
if (fraction.Contains('/'))
{
// If the value contains /, we need to work out the fraction
string[] splitVal = fraction.Split('/');
if (splitVal.Length != 2)
{
ScrewUp(fraction, "splitVal.Length");
}
// Turn the fraction into decimal
value = double.Parse(splitVal[0]) / double.Parse(splitVal[1]);
}
else
{
// Otherwise it's a simple parse
value = double.Parse(fraction);
}
return value;
}
public static double ExtractDistance(string distAsString)
{
double distanceInMeters = 0;
/* This will have a match per unit type.
* e.g., the string "1 1/16 Miles 3/4 Yards" would have 2 matches
* being "1 1/16 Miles", "3/4 Yards". Each match will then have 4
* groups in total, with group 3 being the raw value and 4 being the
* raw unit
*/
var matches = Regex.Matches(distAsString, @"(([\d]+[\d\s\.,/]*)\s([A-Za-z]+[^\s\d]))");
foreach (Match match in matches)
{
// If groups != 4 something went wrong, we need to rethink our regex
if (match.Groups.Count != 4)
{
ScrewUp(distAsString, "match.Groups.Count");
}
string valueRaw = match.Groups[2].Value;
string unitRaw = match.Groups[3].Value;
// Firstly get the value
double value = 0;
if (valueRaw.Contains(' '))
{
// If the value contains /, we need to work out the fraction
string[] splitVal = valueRaw.Split(' ');
if (splitVal.Length != 2)
{
ScrewUp(distAsString, "splitVal.Length");
}
// Turn the fraction into decimal
value = ConvertFraction(splitVal[0]) + ConvertFraction(splitVal[1]);
}
else
{
value = ConvertFraction(valueRaw);
}
// Now work out based on the unit type
// Clean up the raw unit string
unitRaw = unitRaw.ToLower().Trim().TrimEnd('s');
if (!_DistanceLookup.ContainsKey(unitRaw))
{
ScrewUp(distAsString, "unitRaw");
}
distanceInMeters += value * _DistanceLookup[unitRaw];
}
return distanceInMeters;
}
private static void ScrewUp(string val, string prop)
{
throw new ArgumentException("Extract distance screwed up on string [" + val + "] (bad " + prop + ")");
}
享受!我希望有人认为这有用。请留下意见/建议。
编辑:在正则表达式字符串中添加,
以处理1,300 meters
样式格式
答案 1 :(得分:1)
执行此操作的一种方法是向Google发出请求,然后解析返回的html。
更新:这将是非常低效的,但他们已经为您完成了艰苦的工作。为了使这项工作,您必须使用英语(为您的示例)语言解析器来获取输入,去除无意义的单词/符号(如和和逗号),找到值(13和743),找到单位(英里,码和米),找到操作员(在或到)。在那之后,你必须确保它具有语法意义。您还必须保留转换表(并不难)。
这绝对是可能的,但这是一堆工作,而且我不确定是否已存在(除谷歌之外)。你需要担心的角落案例很多。让图书馆完成工作将是一项有趣的练习,但很难捕捉所有案例。
更简单的解决方案是给他们分离控件以解析语言
答案 2 :(得分:0)
这是一个单位转换库。没有所有你想要的测量单位(弗隆!?),但看起来最多:
http://www.codeproject.com/KB/library/Measurement_Conversion.aspx
没有找到任何字符串解析。老实说,这似乎是一种容易出错的输入方式。考虑:
所有意思都是一样的,即使你给出了关于如何写出字符串的具体指示,他们也可能会对他们做出有意义的事情......
如果你想了解人们正在尝试说什么,那么你真的可能会更好地与谷歌合作。否则,您可能会尝试使用特定输入。