Reputation: 681
Given a de-serialized JSON object of arbitrary structure and mixed value types...
var data = {
'a':'A1',
'b':'B1',
'c': [
{'a':'A2', 'b':true},
{'a':'A3', 'b': [1, 2, 3]}
]};
I'd like to return an array of values matching a given key.
> my_func(data, 'a')
['A1', 'A2', 'A3']
> my_func(data, 'b')
['B1', true, [1, 2, 3]]
The closest I've got is this, which gives the right result, but I think there's a better (faster/neater/more efficient) solution.
my_func = function(o,s,a){
var a = a || [];
if(o == null){
return a;
}
if(s in o){
a.push(o[s]);
}
for(e in o){
if(typeof(o[e]) == "object"){
a.concat(my_func(o[e], s, a))
}
}
return a;
}
Any ideas?
Upvotes: 2
Views: 116
Reputation: 681
Thank you all for your input. You've inspired me towards the following solution, which I'm much happier with.
walk_obj = function(o, fn){
for(k in o){
fn(k, o[k]);
if(typeof(o[k]) == "object"){
walk_obj(o[k], fn);
}
}
}
get_by_key = function(o, key){
var a = [];
walk_obj(o, function(k,v){
if(k==key){
a.push(v);
}
})
return a;
}
Upvotes: 0
Reputation:
You can take advantage of the replacer
parameter to JSON.stringify
:
function my_func(data, prop) {
var result = [];
JSON.stringify(data, function(key, val) {
if (key === prop) result.push(val);
return val;
});
return result;
}
Upvotes: 0
Reputation: 12916
function traverse(obj,func, parent) {
for (i in obj){
func.apply(this,[i,obj[i],parent]);
if (obj[i] instanceof Object && !(obj[i] instanceof Array)) {
traverse(obj[i],func, i);
}
}
}
function getPropertyRecursive(obj, property){
var acc = [];
traverse(obj, function(key, value, parent){
if(key === property){
acc.push({parent: parent, value: value});
}
});
return acc;
}
call this like this
getPropertyRecursive( myobj, 'test' )
where myobj
is the nested object and test
is the key
Upvotes: 1