我想從這個字串中得到兩個浮點數
string sample = "#G10F30";
( G 和 F 可以取反)并將它們的值存盤到以下變數中
float g;
float f;
因為我會重復這個 100 次,所以我希望盡可能快。
我可以遍歷所有字符并將數字存盤到兩個不同的字串中,然后將它們的值決議為浮點數,但我想知道是否有更好的方法是合適的。
有什么幫助嗎?
uj5u.com熱心網友回復:
float g;
float f;
string sample = "#G10F30";
//string sample = "#F10G30"; //vice versa
sample = sample.Replace("#", string.Empty);
var splitG = sample.Split("G",StringSplitOptions.RemoveEmptyEntries);
switch (splitG.Length)
{
case 1:
var splitF = splitG[0].Split("F");
g = float.Parse(splitF[0]);
f = float.Parse(splitF[1]);
break;
case 2:
f = float.Parse(splitG[0].Replace("F",string.Empty));
g = float.Parse(splitG[1]);
break;
default:
throw new Exception("Incorrect input string");
}
Console.WriteLine(f);
Console.WriteLine(g);
uj5u.com熱心網友回復:
要詳細說明建議的正則運算式解決方案:
float g = float.NaN;
float f = float.NaN;
string sample = "#G10F30";
foreach (Match m in Regex.Matches(sample, @"(?<var>[FG])(?<val>[ -]?\d (\.\d*)?)"))
{
var variable = m.Groups["var"].Value;
var value = float.Parse(m.Groups["val"].Value);
switch (variable)
{
case "F": f = value; break;
case "G": g = value; break;
}
}
Console.WriteLine($"f={f}, g={g}");
(?<var>[FG])將匹配 F 或 G 并將其分配給組“var”。
(?<val>[ -]?\d (\.\d*)?)將匹配一個浮點數并將其分配給組“val”。
注意:匹配浮點數的正則運算式有點有限,可以根據您的要求進行擴展,請參閱浮點數的正則運算式
uj5u.com熱心網友回復:
你總是可以寫一個決議器:
(float? f, float? g) ParseTwoFloats(string input)
{
if (!input.StartsWith('#')) return (null, null);
var currentBlock = default(char?);
var currentStartIndex = default(int?);
var f = default(float?);
var g = default(float?);
for (var index = 1; index < input.Length; index )
{
var token = input[index];
switch (token)
{
case 'F':
case 'G':
{
if (currentBlock.HasValue) UpdateWithNew(index);
currentBlock = token;
currentStartIndex = index;
break;
}
}
}
if (currentBlock.HasValue) UpdateWithNew(input.Length - 1);
void UpdateWithNew(int index)
{
var value = float.Parse(
input.AsSpan(currentStartIndex.Value 1, index - currentStartIndex.Value - 1),
provider: CultureInfo.InvariantCulture);
switch (currentBlock.Value)
{
case 'F': f = value; break;
case 'G': g = value; break;
}
}
return (f, g);
}
這不會進行堆分配,并且很容易根據您的其他需求進行擴展(例如,添加要決議的其他內容、要跳過的內容、正確的錯誤處理等)。
如果你想要更簡單的東西,你總是可以這樣做:
(float f, float g) ParseTwoFloats(string input)
{
return (FindByToken(input, 'F', 'G'), FindByToken(input, 'G', 'F'));
float FindByToken(string input, char startToken, char endToken) =>
input.IndexOf(startToken) is {} start
? Parse(input, start 1, input.IndexOf(endToken, start))
: 0f;
float Parse(string input, int start, int end) =>
float.Parse(input.AsSpan(start, end == -1 ? input.Length - start : end - start),
provider: CultureInfo.InvariantCulture);
}
這不太靈活,并且確實涉及通過字串的兩次迭代。迭代可以比決議器中的更快。與決議器一樣,沒有堆分配。
如果您將字串輸入替換為另一個 ReadOnlySpan(假設您正在處理較大字串的子字串),您可能會做得更好 - 在決議字串資料時避免堆分配可能會產生巨大的差異。如果您可以避免創建數百萬個子字串,您可以獲得相當不錯的改進。但與往常一樣,先測量。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/490484.html
