使用来自JSON对象的数组表示法进行多级属性检索

时间:2022-05-08 20:21:54

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:

我在这里遇到了一个精神上有问题的问题,我在Backbone中使用一个集合检索了一个JSON对象。这是对象的样子:

{
    "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:

我想对这些数据做什么,是根据特定属性过滤它,例如Venue.Name或Date属性(对象的深度不同,对于其他一些数据可能比两个级别更深) 。我在Backbone集合中有以下代码来过滤并返回一个新的集合,其中包含适当的过滤内容:

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.

这允许我在属性中指定对于任何深度的对象,我想要过滤哪个属性,以及我希望它等于什么。问题是,我真的不想使用“eval”来做这件事,但显然我不能将“[Attribute]”用于像“AwayTeam.TeamID”这样的东西,因为它不起作用。

Does anyone know of a method I can use to achieve this functionality without using eval?

有没有人知道我可以用来实现这个功能而不使用eval的方法?

4 个解决方案

#1


9  

Something 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 Fixtureobject:

您可以将此作为方法添加到Fixtureobject:

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方法重写为

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.net/nikoshr/wjWVJ/3/

和http://jsfiddle.net/nikoshr/wjWVJ/3/一起玩的小提琴

#2


1  

Attributes in JavaScript objects can be accessed by square-bracket, string identifiers as well as the standard dot-notation.

JavaScript对象中的属性可以通过方括号,字符串标识符以及标准点符号来访问。

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 comments, 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.

正如您在注释中指出的那样,这只处理一个级别的对象和属性。要获取嵌套属性,您需要拆分“属性”变量并循环遍历各个部分。我喜欢@ nikoshr的解决方案。

#3


0  

I took nikoshr's answer and added some recursive flair to it:

我拿了nikoshr的答案,并为它添加了一些递归的天赋:

  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

我不确定递归cpu周期是否有很多好处,但我喜欢它们适当时的递归函数

#4


0  

What about using eval() like this:

那么使用eval()如下:

var myObject = {
  
  first: 'Some',
  last: 'Person',
  
  address: {
    city: 'Melbourne',
    country: 'Australia'
  }

}

var propPath = 'address.city';

var city = eval("myObject."+propPath);

console.log(city); // = Melbourne

#1


9  

Something 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 Fixtureobject:

您可以将此作为方法添加到Fixtureobject:

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方法重写为

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.net/nikoshr/wjWVJ/3/

和http://jsfiddle.net/nikoshr/wjWVJ/3/一起玩的小提琴

#2


1  

Attributes in JavaScript objects can be accessed by square-bracket, string identifiers as well as the standard dot-notation.

JavaScript对象中的属性可以通过方括号,字符串标识符以及标准点符号来访问。

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 comments, 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.

正如您在注释中指出的那样,这只处理一个级别的对象和属性。要获取嵌套属性,您需要拆分“属性”变量并循环遍历各个部分。我喜欢@ nikoshr的解决方案。

#3


0  

I took nikoshr's answer and added some recursive flair to it:

我拿了nikoshr的答案,并为它添加了一些递归的天赋:

  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

我不确定递归cpu周期是否有很多好处,但我喜欢它们适当时的递归函数

#4


0  

What about using eval() like this:

那么使用eval()如下:

var myObject = {
  
  first: 'Some',
  last: 'Person',
  
  address: {
    city: 'Melbourne',
    country: 'Australia'
  }

}

var propPath = 'address.city';

var city = eval("myObject."+propPath);

console.log(city); // = Melbourne