有没有比使用jQuery更好的搜索JavaScript数组的方法?

我经常需要搜索包含对象的javascript数组。 我想在数组中搜索具有属性匹配的对象。 例如,在Person对象的数组中搜索person的id / key ===“ABC123”

使用$ .each方法使用jQuery可以很容易地完成它,这是我所确定的。 你可以在jsFiddle中看到这里的例子。 http://jsfiddle.net/johnpapa/EJAFG/

我想知道是否有其他人找到了更快和/或更好的方法来做到这一点?

var Person = function(code, name) { this.code = code; this.name = name; }; var people = [ new Person("ABC123", "Tooth Fairy"), new Person("DEF456", "Santa Claus"), new Person("PIR000", "Jack Sparrow"), new Person("XYZ987", "Easter Bunny") ]; var utils = {}; // Could create a utility function to do this utils.inArray = function(searchFor, property) { var retVal = -1; $.each(this, function(index, item) { if (item.hasOwnProperty(property)) { if (item[property].toLowerCase() === searchFor.toLowerCase()) { retVal = index; return false; } } }); return retVal; }; // or we could create a function on the Array prototype indirectly Array.prototype.inArray = utils.inArray; // let's use the prototype for now var i = people.inArray("PIR000", "code"); $('#output').text(people[i].name); 

有很多问题与此类似,但我还没有看到一个解决方案而不是迭代(就像我在这里做的那样)。

所以问题是……有更好的方法吗?

$ .each将是关于O(n)我会想。 任何简单的“for”循环在找到适用的项目时会中断,最多只能是O(n),但平均来说会更少,除非后续的数组经常被发现是匹配的元素。 Array.filter是一种有效的方法,但不是某些浏览器的原生方法。 如果您希望使用它,则可以使用Array.filter方法的纯JavaScript实现。 对于本机托管它的浏览器,它可能执行得更快,因为它们的实现可能是在本机代码中编译和运行的。 但是过滤方法总是会产生O(n),因为它会将数组的元素“过滤”成一个新数组。

我个人坚持使用for(int i = 0; …)方法。 通过调用其他函数可以减少范围更改的开销,并且可以轻松地“中断”匹配的元素。

我还想补充一点,你可以使用HTML 5提供的本地数据库存储(使用SqlLite)。这显然不受广泛支持,但是在给定足够大的数据集的情况下,它会比任何其他javascript方法快得多。 如果你想查看它,这是一个链接:

http://blog.darkcrimson.com/2010/05/local-databases/

以下是一种有点过时的方法:从理论上讲,您可以将数据编入索引并以快速方式使用这些指标进行检索。 您不是将数据存储在javascript数组中,而是将其存储在DOM中,并使用CSS类(如“data-id-5”)对元素进行“索引”。 这为您提供了使用大多数主流浏览器内置的本机选择器API的优势。 这是一个例子:

DOM:

   

现在我们可以使用jQuery并查询它:我们将查询“ABC123”的键:

 var person = $(".data-id-ABC123").data("person"); console.log(person.name);//Tooth Fairy 

通常,除非您知道要索引的内容,否则无法比O(n)更快地从数组中获取元素。

例如,如果要索引可比较的somethnig,则可以对数组进行排序并执行二进制搜索。

如果您正在对列进行搜索并且值为int或字符串,则可以使用普通Javascript对象作为哈希表。

 var people = [ new Person("ABC123", "Tooth Fairy"), new Person("DEF456", "Santa Claus"), new Person("PIR000", "Jack Sparrow"), new Person("XYZ987", "Easter Bunny") ]; var people_table = {}; for(var i=0; i 

在某个点之后,查询变得太复杂,无法在Javascript中轻松完成,因此发送处理服务器端可能是个好主意,因此您可以使用更合适的工具,例如关系数据库。

这本身并不能解答您的“搜索”问题,但它可能是您的解决方案。 您可以创建一个专门的PersonArray类,为其中的人PersonArray索引。 这种方法的性能是O(1),但它使用更多的内存。

 var PersonArray = function(persons) { this.elements = {}; var i; for (i=0; i < persons.length; i++) { this.elements[persons[i].code] = persons[i]; } }; PersonArray.prototype.fromCode = function(s) { return this.elements[s]; }; var people = new PersonArray([ new Person("ABC123", "Tooth Fairy"), new Person("DEF456", "Santa Claus"), new Person("PIR000", "Jack Sparrow"), new Person("XYZ987", "Easter Bunny") ]); console.log(people.fromCode("ABC123")); // Prints a person console.log(people.fromCode("DEF456")); // Prints a person console.log(people.fromCode("NONE")); // Undefined 

您也可以扩展此方法以索引其他字段。

另请参阅: 演示和基准 (100,000个元素)。

如果您打算这么做,那么您可能希望为特定属性创建索引,以便可以更快地返回项目。 例如,以下实现了一个存储对象,用于添加和获取添加到其中的对象。

它保留了对象名称的索引(如果它们有一个),以便获得它们是有效的。

你只会注意到大量对象的性能提升(比如超过100左右),而且只有那些有索引的人(尽管你可以为任意数量的属性创建一个索引,并且可以使用更通用的方法)去做)。

 function Storage() { this.store = []; this.nameIndex = {}; } // Add item to the store, if has name property, add name to name index Storage.prototype.addItem = function(item) { var idx = this.nameIndex; // If the item has a name property if (item.hasOwnProperty('name')) { // If already have an item with that name, add index of // this item to indexs of same named items if (idx.hasOwnProperty(item.name)) { idx[item.name].push(this.store.length); // Otherwise, add this item to the index } else { idx[item.name] = [this.store.length]; } } // Add the item to the store this.store.push(item); } // Returns a possibly empty array of items with matching names Storage.prototype.getItemsByName = function(name) { var result = []; var names; if (this.nameIndex.hasOwnProperty(name)) { list = this.nameIndex[name]; for (var i=0, iLen=list.length; i 

也许你可以用for..in循环它。 请参阅: http : //www.w3schools.com/js/js_loop_for_in.asp 。 像php的foreach一样以类似的方式工作。

如果我必须重复搜索一个数组,那么我迭代一次,在其中我将每个键添加为一个对象的属性,然后在该对象中查找键。 这使所有查找的目标保持在O(n)+ c。 存储是有效的,因为对象存储对数组数据的引用,或者它们是基元。 简单快捷。