【问题标题】:Efficient parsing of a string into float array in JavaScript在 JavaScript 中将字符串高效解析为浮点数组
【发布时间】:2012-11-26 11:34:09
【问题描述】:

Collada 文件格式包含大量数据,这些数据以空格分隔的浮点/整数/布尔值列表形式存储。这些列表可能巨大。我们大致使用以下代码在 JavaScript 中解析这些列表:

var floats = input.split(' ').map(parseFloat)

但这会产生大量垃圾,因为巨大的输入字符串被分割成数千个单独的小字符串。有没有办法避免这种情况?类似于 parseFloat() 函数的东西,我可以指向现有字符串中的偏移量,从而避免生成垃圾。

【问题讨论】:

  • 为什么其余的都是垃圾?您一次只需要一个值吗?
  • “垃圾”是什么意思?您是在谈论内存使用情况,例如需要进行垃圾收集的临时字符串数组,还是只是垃圾,例如您不想要的值?没有从字符串中的偏移量中提取的parseFloat() 变体。您可以在循环中使用.indexOf().substr() 手动提取子字符串或其他内容,但这会创建同样多的字符串(它们不会同时全部保存在数组中)。当前的代码是否表现不佳?
  • 是的,我说的是split() 创建的小临时字符串。 substring() 也将创建这些。我需要所有的花车。
  • 没有办法避免创建这些临时字符串,但是包含几千个短字符串的数组应该不是问题 - 您是否遇到内存问题?

标签: javascript optimization


【解决方案1】:

如果你在你的字符串前面加上一个空格,你可以用它来从字符串中取出第一个数字:

var start = 0 // Initial search offset.
var firstOccurence = input.indexOf(' ', start);
//Get the substring from the first occurrence of ' ' after start, to the next one, and parse it as a float.
parseFloat(input.substring(firstOccurence , input.indexOf(' ', firstOccurence+1)));

然后,您可以使用以下内容从字符串中获取之后的数字:

firstOccurence = t.indexOf(' ', firstOccurence+1);
parseFloat(t.substring(firstOccurence , t.indexOf(' ', firstOccurence+1)));

在循环中使用它,您可以搜索您的列表,并且可以从指定索引处开始搜索列表。但是,例如,您不能要求列表中的第 7 个浮点数。唯一可靠的方法是使用.split(' '),或者循环使用上述代码。

要在输入中找到nth 浮点数,可以使用以下命令:

for(var i = 0, previousIndex = 0; i < n; i++){
    previousIndex = input.indexOf(' ', previousIndex + 1);
}
var float = parseFloat(input.substring(previousIndex, input.indexOf(' ',  previousIndex + 1)));

【讨论】:

  • ++lastIndex 实际上并没有改变lastIndex 的值,因为它是lastIndex 赋值右侧的一部分
  • 刚刚在 chrome 控制台中尝试过。在右侧预增加一个变量确实会改变变量的值。var x = 0; var v = ++x; x //=&gt;1; v //=&gt;1;
  • 嗯,这很好。不过,我仍然更喜欢在这里使用 +1。其他用户可能会复制/粘贴/编辑...
  • @Bruno 不,试试var v= 0; v = v++;。这将导致 v 为零。原件不受影响,但您将其用作不同作业的 RHS。
  • v = 0; v = ++v; v = ++v; //=&gt; 0, 1, 2 Chrome 和 Firefox 都递增 v.
【解决方案2】:

此函数可以处理多个空格以及不解析为浮点数的输入。

input = "123 123 123  foo", start = 0, end = 0, result = [], num;

// empty string evaluates to false
while( end < input.length ) {
    end = input.indexOf(" ", start );
    // -1 => only one element in input || end of the string has been reached
    if( end === -1 ) { end = input.length }
    num =  parseFloat( input.substring( start, end ) );
    // Should extracted string fail to parse then skip
    if( num ) result.push( num ); 
    // move forward or end will match current empty space
    start = end + 1;
}

result[2] // => "123";

小提琴here

更新

刚刚有一个脑电波。不要使用 map 函数,而只使用通过拆分字符串创建的数组,如下所示:

var floats = input.split(' ');
for( var i = 0, len = input.length; i < len; i++ ) {
    input[i] = parseFloat( input[i] );
}

【讨论】:

  • @wereHamster 我最后的建议是否真的符合您的要求。
【解决方案3】:

这个怎么样?

parseFloat(input.substring(5,10));

5,10 是您想要的字符串块的开始和结束偏移量。

【讨论】:

    猜你喜欢
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多