0

I have a javascript assoc array (object) like

aa = {"(one)":["a","b","c"], "(two)":["d","e","f"]}

and a string like

s = "(two) blah blah (one) etc (two)"

I want to turn the assoc array into a plain array whose order is as specified in the string

newarray = [["d","e","f"] , ["a","b","c"], ["d","e","f"]]

The only thing is, the array and string may contain many millions of items. If I do this using string.match with the global modifier, then iterating over the results, will I end up using huge amounts of memory? Is there a way to iterate over matches in the string without storing the text of all the matches (a bit like a iterator version of string.search)?

4
  • There are no assoc arrays, that's an object (again). Commented Jun 9, 2014 at 9:07
  • use string.split passing in a regular expression to split by the (one),(two) etc, perhaps? Then just iterate through the array returned to build your newarray? Commented Jun 9, 2014 at 9:15
  • @adeneo, I was using "assoc array" as shorthand. It's all hashed storage anyway. Commented Jun 9, 2014 at 9:18
  • @PulseLab thanks, but won't that end up storing huge numbers of extra strings. Or does string.split do compiler magic so that new substrings are actually created, just providing a "view" into the original static string that can be iterated over? Commented Jun 9, 2014 at 9:23

2 Answers 2

1

I'm thinking something along these lines, based on a regular expression:

var aa = {"(one)":["a","b","c"], "(two)":["d","e","f"]};
var s = "(two) blah blah (one) etc (two)";
var result = [];

s.match(/(\(.+?\))/g).forEach(function(match) {
    result.push(aa[match]);
});
Sign up to request clarification or add additional context in comments.

3 Comments

Ideal, if s.match().forEach is optimised by the compiler to act as an iterator, rather than having to store an intermediate array of all the matches. I suspect it is optimised like this. Will try. Thanks!
Yeah not sure about that optimization... Depends on the Javascript engine, but not sure if any of them would optimize it this way. If not, you could use RegExp.exec() to do progressive matching.
Aha - I didn't spot that RegExp.exec() did progressive matching (docs). That's probably just what I need. Thanks.
1
var aa = {"(one)":["a","b","c"], "(two)":["d","e","f"]};
var s = "(two) blah blah (one) etc (two)"
var newarray = [];
var res = s.match(/\((.*?)\)/g);
var i = 0;
while (i < res.length){
    newarray.push(aa[res[i]]); 
    i++;
}
console.log(newarray);

Finally this one works perfectly.

http://jsfiddle.net/KRzRj/

5 Comments

This does not take the string into account at all.
Sorry, too fast with my comment. Didn't realize you were still editing. Solution still doesn't look correct though...
That will construct an array in the order returned by the for(key in aa) call. On my machine that returns (one) first, then (two), so it gets the order wrong (newarray = [["a","b","c"], ["d","e","f"] , ["d","e","f"]])
@user2667066 I did some edit and the answer is now exactly what your looking for [["d","e","f"] , ["a","b","c"], ["d","e","f"]]
But that still stores an intermediate array in res. See my comment above, I think progressive RegExp.exec is what I need.

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.