admin管理员组文章数量:1277338
I've got a mentally taxing problem here, where I've got a JSON object retrieved using a collection in Backbone. This is what the object looks like:
{
"MatchID": "00000001",
"Date": "1970-01-01T00:00:00.000Z",
"OriginalID": "",
"Stage": {
"StageNumber": "0",
"StageType": "Stage Type"
},
"Round": {
"RoundNumber": "0",
"Name": "Round Name"
},
"Leg": "1",
"HomeTeam": {
"TeamID": "0",
"Name": "Home Team Name"
},
"AwayTeam": {
"TeamID": "0",
"Name": "Away Team Name"
},
"Venue": {
"VenueID": "0",
"Name": "Venu Name"
},
"Referee": null,
}
What I want to do with this data, is filter it based on a particular attribute, such as the Venue.Name or Date attributes (which are different depths into the object, and can be deeper than two levels for some of the other data). I've got the following code inside a Backbone collection to filter and return a new collection with the contents filtered appropriately:
findWhere: function (Attribute, Value)
{
return new Project.Collections.Fixtures(this.filter(function (fixture)
{
return eval('fixture.attributes.' + Attribute) == Value;
}));
}
This allows me to specify in an attribute which attribute I want to filter by, and what I want it to be equal to, for any depth of object. The problem is, I really don't want to use "eval" to do this, but obviously I can't use "[Attribute]" for something like "AwayTeam.TeamID", as it won't work.
Does anyone know of a method I can use to achieve this functionality without using eval?
I've got a mentally taxing problem here, where I've got a JSON object retrieved using a collection in Backbone. This is what the object looks like:
{
"MatchID": "00000001",
"Date": "1970-01-01T00:00:00.000Z",
"OriginalID": "",
"Stage": {
"StageNumber": "0",
"StageType": "Stage Type"
},
"Round": {
"RoundNumber": "0",
"Name": "Round Name"
},
"Leg": "1",
"HomeTeam": {
"TeamID": "0",
"Name": "Home Team Name"
},
"AwayTeam": {
"TeamID": "0",
"Name": "Away Team Name"
},
"Venue": {
"VenueID": "0",
"Name": "Venu Name"
},
"Referee": null,
}
What I want to do with this data, is filter it based on a particular attribute, such as the Venue.Name or Date attributes (which are different depths into the object, and can be deeper than two levels for some of the other data). I've got the following code inside a Backbone collection to filter and return a new collection with the contents filtered appropriately:
findWhere: function (Attribute, Value)
{
return new Project.Collections.Fixtures(this.filter(function (fixture)
{
return eval('fixture.attributes.' + Attribute) == Value;
}));
}
This allows me to specify in an attribute which attribute I want to filter by, and what I want it to be equal to, for any depth of object. The problem is, I really don't want to use "eval" to do this, but obviously I can't use "[Attribute]" for something like "AwayTeam.TeamID", as it won't work.
Does anyone know of a method I can use to achieve this functionality without using eval?
Share Improve this question edited May 29, 2012 at 12:51 brins0 asked May 29, 2012 at 12:45 brins0brins0 3251 gold badge5 silver badges14 bronze badges4 Answers
Reset to default 9Something like this would let you traverse the hierarchy of objects to find a value:
var x = {
y: {
z: 1
}
};
function findprop(obj, path) {
var args = path.split('.'), i, l;
for (i=0, l=args.length; i<l; i++) {
if (!obj.hasOwnProperty(args[i]))
return;
obj = obj[args[i]];
}
return obj;
}
findprop(x, 'y.z');
You could add this as a method to your Fixture
object:
Fixture = Backbone.Model.extend({
findprop: function(path) {
var obj = this.attributes,
args = path.split('.'),
i, l;
for (i=0, l=args.length; i<l; i++) {
if (!obj.hasOwnProperty(args[i]))
return;
obj = obj[ args[i] ];
}
return obj;
}
});
and use it to extract the value
var f = new Fixture();
f.findprop("HomeTeam.TeamID");
The findWhere
method could then be rewritten as
findWhere: function (Attribute, Value)
{
return new Project.Collections.Fixtures(this.filter(function (fixture){
return fixture.findprop(Attribute) === Value;
}));
}
And a Fiddle to play with http://jsfiddle/nikoshr/wjWVJ/3/
Attributes in JavaScript objects can be accessed by square-bracket, string identifiers as well as the standard dot-notation.
In other words, this:
fixture.attributes.something
is the same as this:
fixture.attributes["something"]
You can also pass variable names in to the square brackets, the value of the variable is used as the key to retrieve.
So you can change your code to this:
findWhere: function (Attribute, Value)
{
return new Project.Collections.Fixtures(this.filter(function (fixture)
{
return fixture.attributes[Attribute] === Value;
}));
}
As you pointed out in the ments, this only handles one level objects and attributes. To get the nested attributes, you'll need to split the "Attribute" variable and loop through the parts. I like @nikoshr's solution for that.
What about using eval()
like this:
var myObject = {
first: 'Some',
last: 'Person',
address: {
city: 'Melbourne',
country: 'Australia'
}
}
var propPath = 'address.city';
var city = eval("myObject."+propPath);
console.log(city); // = Melbourne
I took nikoshr's answer and added some recursive flair to it:
var findprop = function (obj, path) {
var args = (typeof path === 'string') ? path.split('.') : path,
thisProperty = obj[args[0]];
if (thisProperty === undefined) { return; } //not found
args.splice(0, 1); //pop this off the array
if (args.length > 0) { return findprop(thisProperty, args); } //recurse
else {return thisProperty; }
};
I'm not sure if there is much benefit to the recursion cpu cycle-wise, but I like recursive functions when they are appropriate
本文标签: javascriptMultiple level attribute retrieval using array notation from a JSON objectStack Overflow
版权声明:本文标题:javascript - Multiple level attribute retrieval using array notation from a JSON object - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741222252a2361186.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论