解析子串直接加倍

Jon*_*rop 6 .net c# f#

如果我有一个字符串,1 2 3并且我确定包含a的子字符串的位置,double我如何直接从子字符串解析它而不创建临时字符串?

例如,我可以这样做System.Double.Parse(str.Substring(0, 1))但会创建一个缓慢且不必要的临时字符串.是否可以直接从原始字符串的一部分解析double?

编辑

Eric Lippert在这里质疑我的动机,说"小弦很便宜".这样做的动机来自于我对int的解析和看到大量的性能提升做同样的事情,因为显然,小字符串不是那么便宜.

这是一个通过临时字符串来修改一系列int的函数:

let lex f (s: string) =
  let rec inside i0 (s: string, i) =
    if i = s.Length then
      f (s.Substring(i0, i-i0) |> System.Int32.Parse)
    else
      let c = s.[i]
      if '0'<=c && c<='9' then
        inside i0 (s, i+1)
      else
        f (s.Substring(i0, i-i0) |> System.Int32.Parse)
        outside (s, i)
  and outside (s: string, i) =
    if i < s.Length then
      let c = s.[i]
      if '0'<=c && c<='9' then
        inside i (s, i)
      else
        outside (s, i+1)
  outside (s, 0)
Run Code Online (Sandbox Code Playgroud)

这需要2.4s到一个字符串的lex 15,625,000 int.

这是一个避免临时字符串的版本:

let lex f (s: string) =
  let rec inside n (s: string, i) =
    if i = s.Length then f n else
      let c = s.[i]
      if '0'<=c && c<='9' then
        inside (10*n + int c - int '0') (s, i+1)
      else
        f n
        outside (s, i)
  and outside (s: string, i) =
    if i < s.Length then
      let c = s.[i]
      if '0'<=c && c<='9' then
        inside 0 (s, i)
      else
        outside (s, i+1)
  outside (s, 0)
Run Code Online (Sandbox Code Playgroud)

这需要0.255秒,比使用临时字符串的解决方案快9倍!

我认为没有理由为什么lexing浮标应该有所不同.因此,通过不提供从子字符串解析浮点数的能力,.NET在表上保留了一个数量级的性能.我做了很多科学计算,经常不得不哄骗大量的数据,特别是在初创公司时,所以我真的不想像这样把性能抛到脑后.

jdw*_*eng -2

这是你能做的最好的事情

static void Main(string[] args)
{
    string input = "1 2 3";
    double[] output = input.Split(new char[] {' '},StringSplitOptions.RemoveEmptyEntries).Select(x => double.Parse(x)).ToArray();
}
Run Code Online (Sandbox Code Playgroud)

  • 这添加了 3 个数组、一个“IEnumerable”和一个“Func”的额外分配。考虑到 OP 甚至不能容忍单个字符串分配,我认为这不符合要求。 (2认同)