2

The Collada file format contains lots of data which is stored as whitespace delimited list of float/int/boolean values. These lists can be huge. We parse these lists in JavaScript using roughly the following code:

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

But this generates a lot of garbage because the huge input string is split into thousands of individual small strings. Is there a way to avoid that? Something like a parseFloat() function which I can point at a offset within an existing string, and so avoid generating the garbage.

4
  • Why are the rest of them garbage? Do you only need one value at a time? Commented Nov 26, 2012 at 11:39
  • What do you mean by "garbage"? Are you talking about memory usage, as in that temporary array of strings that will need to be garbage-collected, or just garbage as in values you don't want? There is no parseFloat() variation that extracts from an offset in a string. You could manually extract substrings using .indexOf() and .substr() in a loop or something, but that would create just as many strings overall (they just wouldn't all be held in an array simultaneously). Is the current code performing badly? Commented Nov 26, 2012 at 11:39
  • Yes, I'm talking about the small temporary strings that split() creates. substring() will also create those. And I need all the floats. Commented Nov 26, 2012 at 11:49
  • There's no way to avoid creating those temporary strings, but an array with a few thousand short strings shouldn't be a problem - are you experiencing memory problems? Commented Nov 26, 2012 at 20:47

3 Answers 3

2

If you prefix your string with one space, you can use this to get the first number out of the string:

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

Then, you can use the following to get the numbers after that, out of the string:

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

Using this in a loop, you can search through your list, and you can start searching the list at a specified index. You can't however, ask for the 7th float in the list, for example. The only reliable way to do that is to use .split(' '), or to use the above code in a loop.

To find the nth float in the input, you can use the following:

for(var i = 0, previousIndex = 0; i < n; i++){
    previousIndex = input.indexOf(' ', previousIndex + 1);
}
var float = parseFloat(input.substring(previousIndex, input.indexOf(' ',  previousIndex + 1)));
Sign up to request clarification or add additional context in comments.

20 Comments

++lastIndex doesn't actually change the value of lastIndex, since it is part of the right hand side of an assignment to lastIndex
Just tried in the chrome console. pre-incrementing a variable on the right hand-side DOES change the value of the variable.var x = 0; var v = ++x; x //=>1; v //=>1;
Hm, that's a good point. I'd still prefer to use +1 here, though. Other users might copy/paste/edit...
@Bruno Nope, try var v= 0; v = v++;. It will result in v being zero. The original isn't affected, but you're using it as the RHS of a different assignment.
v = 0; v = ++v; v = ++v; //=> 0, 1, 2 Both Chrome and Firefox increment v.
|
2

This function can handle multiple white spaces as well as input that does not parse as a float.

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

Fiddle here

UPDATE

Just had a brainwave. Don't use the map function but just use the array created by splitting the string like so:

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

1 Comment

@wereHamster Does my last suggestion actually do what you were looking for.
1

How about this?

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

Where 5,10 are the starting and ending offsets of your desired chunk of string.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.