G
Gabriel Gilini
Hi, I came to the need of extracting the 'href' property from the
StyleSheet objects contained within document.styleSheets object. So,
as a (lame) attempt to build something like CakePHP's Set::extract
function[1], which uses XPath sintax to extract subsets of an array, I
came up to this:
function extract(path, iterable){
if((typeof iterable.length != 'number') || (path.indexOf('/') !==
0)){
return false;
}
if(path == '/'){
return iterable;
}
var filtered = [];
var arrLikePath = '["' + path.slice(1).replace('/', '"]["', 'g') +
'"]';
var getVal = new Function('return arguments[0]' + arrLikePath);
for(var i = 0, len = iterable.length, tmpVal; i < len; ++i){
try{
tmpVal = getVal(iterable);
filtered.push(tmpVal);
}
catch(err){}
}
return filtered;
}
It's obviously far from a XPath 'selector', but it allows me to do
something like - extract('/href', document.styleSheets) - which is
fine for now.
After doing this, I realized that this function could be useful when
dealing with JSON-formatted data from some API's, and now I'd like to
make it efficient.
My main problem now is determining if a certain property exists in an
object, independent of its depth. For my lame extract function I used
the try/catch statement, but with large data sets where a lot of - foo
is undefined - exceptions can be thrown, the execution gets
ridiculously slow.
I thought of making a helper function which would recursively check
for the properties, but it just feels like this should be simpler.
Anyway, I'll do it and post the results here, just in case anyone is
interested. I'm using the following document to test it:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Extract Test</title>
<script type="text/javascript" src="extract.js"></script>
<script type="text/javascript">
function appendText(string, father){
var pE = document.createElement('p');
var tN = document.createTextNode(string);
pE.appendChild(tN);
father.appendChild(pE);
}
window.onload = function(){
var r = document.getElementById('results');
var foo = [];
for(var i = 0; i < 1000; ++i){
if(i % 2){
foo = {'bar': 'bar'};
}else{
foo = {'bar': 'bar', 'baz': {'theAnswer':
42}};
}
}
var dt = new Date;
var res = extract('/baz/theAnswer', foo);
dt = (new Date) - dt;
appendText(dt + 'ms', r);
appendText("result array length: " + res.length , r);
}
</script>
</head>
<body>
<div id="results">
</div>
</body>
</html>
With 500 errors thrown, the code takes 1,5 seconds to execute. I'm
pretty sure that any kind of recursive checking function would top
that for a two-level-deep subject.
Any thoughts about this are welcome.
[1] http://book.cakephp.org/view/671/extract
StyleSheet objects contained within document.styleSheets object. So,
as a (lame) attempt to build something like CakePHP's Set::extract
function[1], which uses XPath sintax to extract subsets of an array, I
came up to this:
function extract(path, iterable){
if((typeof iterable.length != 'number') || (path.indexOf('/') !==
0)){
return false;
}
if(path == '/'){
return iterable;
}
var filtered = [];
var arrLikePath = '["' + path.slice(1).replace('/', '"]["', 'g') +
'"]';
var getVal = new Function('return arguments[0]' + arrLikePath);
for(var i = 0, len = iterable.length, tmpVal; i < len; ++i){
try{
tmpVal = getVal(iterable);
filtered.push(tmpVal);
}
catch(err){}
}
return filtered;
}
It's obviously far from a XPath 'selector', but it allows me to do
something like - extract('/href', document.styleSheets) - which is
fine for now.
After doing this, I realized that this function could be useful when
dealing with JSON-formatted data from some API's, and now I'd like to
make it efficient.
My main problem now is determining if a certain property exists in an
object, independent of its depth. For my lame extract function I used
the try/catch statement, but with large data sets where a lot of - foo
is undefined - exceptions can be thrown, the execution gets
ridiculously slow.
I thought of making a helper function which would recursively check
for the properties, but it just feels like this should be simpler.
Anyway, I'll do it and post the results here, just in case anyone is
interested. I'm using the following document to test it:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Extract Test</title>
<script type="text/javascript" src="extract.js"></script>
<script type="text/javascript">
function appendText(string, father){
var pE = document.createElement('p');
var tN = document.createTextNode(string);
pE.appendChild(tN);
father.appendChild(pE);
}
window.onload = function(){
var r = document.getElementById('results');
var foo = [];
for(var i = 0; i < 1000; ++i){
if(i % 2){
foo = {'bar': 'bar'};
}else{
foo = {'bar': 'bar', 'baz': {'theAnswer':
42}};
}
}
var dt = new Date;
var res = extract('/baz/theAnswer', foo);
dt = (new Date) - dt;
appendText(dt + 'ms', r);
appendText("result array length: " + res.length , r);
}
</script>
</head>
<body>
<div id="results">
</div>
</body>
</html>
With 500 errors thrown, the code takes 1,5 seconds to execute. I'm
pretty sure that any kind of recursive checking function would top
that for a two-level-deep subject.
Any thoughts about this are welcome.
[1] http://book.cakephp.org/view/671/extract