0

假设我有以下 javascript

var myobj = {
   name: "Julia",
   birthdate: "xxxx",
   movies: [{title: "movie1", rating: 5, genre: "Horror"}, {title: "movie2", rating 3, genre: "Comedy"},{title: "movie3", rating 3, genre: "Comedy"}, {title: "movie4", rating 3, genre: "Comedy"}, {title: "movie5", rating 3, genre: "Horror"}]
}

我正在寻找检索所有“恐怖”电影(可能是喜剧)的最佳方式,而无需遍历数组中的所有内容。我知道我可以创建一个 for 循环来使用 if 条件遍历电影数组,但这需要我浏览每一部电影。如果有什么办法我可以做到:

horrorMovies = [//array containing all horror movies without iterating through everything to iterate through all moves to look at their genre attribute]

或者在 myobj 中有一些附加字段作为某种查找表是一种好的做法:

myobj.genreindexes = [];

并跟踪所有类型,例如:genreindexes['Horror'] = '//Array index where element is Horror'?

或者有什么简单的方法可以做:myobj.movi​​es['-insertgenrehere-'] 并获取电影列表?任何建议和样品将不胜感激。

如果没有理想的解决方案,使用任何库的样本也可以。

4

4 回答 4

1

分离,

在不遍历所有对象的情况下访问一组具有相同特征的对象的唯一方法是在插入它们时将它们全部放入一个框中。当然,当我说盒子时,我的意思是把它们放在一起的数据结构中。

也就是说,这里有一些不同的场景需要考虑:

  1. 您为一大桶项目编写了一个迭代器,并告诉迭代器提取您想要的内容。实际上,您正在迭代所有项目,但它允许您在查询所需内容时变得“懒惰”。这可能不是你想要的。

  2. 你真的想用一些共同的财产把它们分开。在这种情况下,您为每个公共属性(哈希表)创建单独的存储桶。

我会推荐选项 2,因为它可以快速访问您想要的内容。

这是一个解释如何在 Javascript 中使用哈希表的链接: http ://www.mojavelinux.com/articles/javascript_hashes.html

于 2012-07-12T16:34:04.973 回答
0

正如您所提到的,基于流派存储标题索引可能是保证性能改进的最佳方式(或者您可以使用排序存储和二进制搜索等,但我认为这将是一种矫枉过正)。一种干净的方法是添加一个名为pushMovie(_name, _genre, ...)Array 原型的函数并将其用于填充您的电影。在里面pushMovie(..)你也可以编写代码来填充索引..

于 2012-07-12T16:24:25.307 回答
0

好吧,我认为使用 jLinq 来做你需要的一个可能的好方法。

库: https ://raw.github.com/hugoware/jlinq-beta/master/jlinq.js

这是我的代码,但我也给你做了一个 jsfiddle:

演示:http: //jsfiddle.net/oscarj24/anMDt/

//Your json obj array
var myobj = {
   name: "Julia",
   birthdate: "xxxx",
   movies: [{title: "movie1", rating: 5, genre: "Horror"}, {title: "movie2", rating: 3, genre: "Comedy"},{title: "movie3", rating: 3, genre: "Comedy"}, {title: "movie4", rating: 3, genre: "Comedy"}, {title: "movie5", rating: 3, genre: "Horror"}]
}

//Just horror movies in object
var horrorMovies = jlinq.from(myobj.movies).starts('genre', 'Horror').select();

// See the console with your horror movies
console.log(horrorMovies);

结果:

在此处输入图像描述

希望这可以帮助 :-)

于 2012-07-12T16:52:20.713 回答
0

执行一次线性传递,并为所有字段生成索引。是的,这不是零成本;但话又说回来,没有免费的午餐。

一般而言,

function index(array) {
    var fields = {}
    for (var i=0; i<array.length; i++) {
        var o = array[i]
        for (var f in o) {
            if ( ! o.hasOwnProperty(f)) {
               continue;
            } else if (fields[f] === undefined) {
                fields[f] = {};
                fields[f][o[f]] = [o];
            } else if (fields[f][o[f]] === undefined) {
                fields[f][o[f]] = [o];
            } else {
                fields[f][o[f]].push(o);
            }
        }
    }
    return fields;
}

这允许你写

var db = index(myobj.movies); // takes O(C), where C = number of rows x cols 
db["genre"]["Comedy"];         // returns an array w/ movies 2, 3, 4 - in O(1)
db["genre"]["Horror"];         // returns an array w/ movies 1, 5
...

经典的空间换时间权衡。另外,看看它的工作原理(JsFiddle)

于 2012-07-12T16:57:49.410 回答