简体   繁体   English

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

[英]Is there a Better Way to Search a JavaScript Array than Using jQuery's each?

I often have the need to search a javascript array that contains objects. 我经常需要搜索包含对象的javascript数组。 I want to search for an object in the array that has a property match. 我想在数组中搜索具有属性匹配的对象。 For example, searching an array of Person objects for where the person's id/key === "ABC123" 例如,在Person对象的数组中搜索person的id / key ===“ABC123”

It can be done pretty easily using jQuery using the $.each method, which is what I settled on. 使用$ .each方法使用jQuery可以很容易地完成它,这是我所确定的。 You can see the example here in jsFiddle. 你可以在jsFiddle中看到这里的例子。 http://jsfiddle.net/johnpapa/EJAFG/ http://jsfiddle.net/johnpapa/EJAFG/

I'm wondering if anyone else has found a faster and/or better way to do this? 我想知道是否有其他人找到了更快和/或更好的方法来做到这一点?

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);

There are lot's of questions similar to this one, but I have yet to see one with a solution other than iterating (like I did here). 有很多问题与此类似,但我还没有看到一个解决方案,而不是迭代(就像我在这里做的那样)。

So the question is ... is there a better way? 所以问题是......有更好的方法吗?

$.each would be about O(n) I would think. $ .each将是关于O(n)我会想。 Any simple "for" loop that breaks when it finds an applicable item would be at most O(n) but would on average be less unless the latter items of the array were constantly found to be the matching elements. 任何简单的“for”循环在找到适用的项目时会断开,最多只能是O(n),但平均来说会更少,除非数组的后一项经常被发现是匹配元素。 Array.filter is a method that works but is not native to some browsers. Array.filter是一种有效的方法,但不是某些浏览器的原生方法。 There are pure javascript implementations of the Array.filter method if you so wished to use it. 如果你希望使用它,那么Array.filter方法有纯粹的javascript实现。 For the browsers that host it natively, it would probably execute faster as their implementation is probably compiled and ran in native code. 对于本机托管它的浏览器,它可能执行得更快,因为它们的实现可能是在本机代码中编译和运行的。 But the filter method would always yield O(n) as it "filters" the elements of the array into a new array. 但是过滤器方法总是会产生O(n),因为它将数组的元素“过滤”成一个新数组。

I'd personally stick with the for(int i=0;...) approach. 我个人坚持使用for(int i = 0; ...)方法。 Less overhead of scope changing by calling other functions and you can easily "break" on a matched element. 通过调用其他函数可以减少范围更改的开销,并且可以轻松地“中断”匹配的元素。

I also wanted to add that you could use local database storage(which uses SqlLite) provided by HTML 5. This is obviously not widely supported but would be MUCH faster than any other javascript approach given a large enough set of data. 我还想补充一点,你可以使用HTML 5提供的本地数据库存储(使用SqlLite)。这显然不受广泛支持,但是在给定足够大的数据集的情况下,它会比任何其他javascript方法快得多。 Here is a link if you want to check it out: 如果你想查看它,这是一个链接:

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

Here is a somewhat off the wall way of doing it: You could theoretically index your data and retrieve it using those indicies in a fast manner. 以下是一种有点不太常见的做法:理论上,您可以将数据编入索引并以快速方式使用这些指标进行检索。 Instead of storing your data in a javascript array, you store it in the DOM and "index" the elements using CSS classes like "data-id-5". 您不是将数据存储在javascript数组中,而是将其存储在DOM中,并使用CSS类(如“data-id-5”)对元素进行“索引”。 This gives you the advantage of using the native selector API built-in to most major browsers. 这为您提供了使用大多数主流浏览器内置的本机选择器API的优势。 Here is an example: 这是一个例子:

DOM: DOM:

 <div id="datastuff" style="display:none">
     <span class="data-id-ABC123" data-person='{"code": "ABC123", "name": "Tooth Fairy"}'></span>
     <span class="data-id-DEF456" data-person='{"code": "DEF456", "name": "Santa Claus"}'></span>
     <span class="data-id-PIR000" data-person='{"code": "PIR000", "name": "Jack Sparrow"}'></span>
     <span class="data-id-XYZ987" data-person='{"code": "XYZ987", "name": "Easter Bunny"}'></span>
 </div>

Now we can use jQuery and query for it: We'll query for key of "ABC123": 现在我们可以使用jQuery并查询它:我们将查询“ABC123”的键:

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

In general you can't get elements from an array faster then O(n) unless you know something about what you want to index. 通常,除非您知道要索引的内容,否则无法比O(n)更快地从数组中获取元素。

For example, if you are indexing somethnig that is comparable you can sort the array and do binary search. 例如,如果要索引可比较的somethnig,则可以对数组进行排序并执行二进制搜索。

If you are doing searches on a column and the values are ints or strings you can use plain Javascript objects as hash tables. 如果您正在对列进行搜索并且值为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<people.length; i++){
    people_table[ people[i].id ] = people[i];
}

//fast search:
var someone = people_table['ABC123'];

After a certain point queries get too complex to easily do by hand in Javascript so it might be a good idea to send the processing server-side so you can use a more appropriate tool, like as a relational database. 在某一点之后,查询变得太复杂,无法在Javascript中轻松完成,因此发送处理服务器端可能是个好主意,因此您可以使用更合适的工具,例如关系数据库。

This doesn't answer your "search" question per se, but it may be a solution for you. 这本身并不能解答您的“搜索”问题,但它可能是您的解决方案。 You can create a specialized PersonArray class which indexes the people within it. 您可以创建一个专门的PersonArray类,为其中的人PersonArray索引。 The performance with this approach is O(1), but it uses more memory. 这种方法的性能是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

You can extend this approach to index other fields, as well. 您也可以扩展此方法以索引其他字段。

Also see: a demo and a benchmark (with 100,000 elements). 另请参阅: 演示基准 (100,000个元素)。

If you intend to do this a lot, then you might want to create an index for specific properties so that items can be returned much faster. 如果您打算这么做,那么您可能希望为特定属性创建索引,以便可以更快地返回项目。 eg the following implements a storage object that add and gets objects that are added to it. 例如,以下实现了一个存储对象,用于添加和获取添加到其中的对象。

It keeps an index of object names (if they have one) so that getting them is efficient. 它保留了对象名称的索引(如果它们有一个),以便获得它们是有效的。

You'll only notice a performance bump for a large number of objects though (say more than 100 or so) and only for those with an index (though you can create an index for any number of properties and could have a more generic method to do that). 您只会注意到大量对象的性能提升(例如超过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<iLen; i++) {
        result.push(this.store[list[i]]);
      }
  }
  return result;
}

// Generic method for any property and value
Storage.prototype.getItemsByAttributeValue = function(propName, propValue) {
  // loop through items, return array of 
  // those with matching property and value
}


var store = new Storage();

store.addItem({name:'fred',age:'9'});

var obj = store.getItemsByName('fred');

alert(obj[0].age); // 9

store.addItem({name:'sally',age:'12'});

obj = store.getItemsByName('sally');

alert(obj[0].age); //12

If I have to search an array repeatedly, then I iterate it once, in which I add each key as a property of an object, and then look up the key in that object. 如果我必须重复搜索数组,那么我迭代一次,在其中我将每个键添加为对象的属性,然后在该对象中查找键。 This keeps the aim of all lookups at O (n)+c. 这使所有查找的目标保持在O(n)+ c。 Storage is efficient as the object is storing references to the array data, or they are primitives. 存储是有效的,因为对象存储对数组数据的引用,或者它们是基元。 Simple and fast. 简单快捷。

Maybe you can loop it with a for..in. 也许你可以用for..in循环它。 See: http://www.w3schools.com/js/js_loop_for_in.asp . 请参阅: http//www.w3schools.com/js/js_loop_for_in.asp Works in a similair fashion as php's foreach. 像php的foreach一样以类似的方式工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在JavaScript中是否有更好的方法可以做到这一点? 使用while进行数组搜索 - Is there a better way to do this in JavaScript? Array search using while 通过使用JQuery来检测父级的子级数组中的索引的更好方法? - A better way to detect the index in the parent's children array by using JQuery? 比在JQuery中使用文档就绪更好的方法 - Better way than using document ready in JQuery Javascript:将数组拼接在一起比将我现在使用的更好的方法是什么? - Javascript: What's a better way to splice arrays together than what I'm using now? Javascript:使用Jquery的bind()出价事件是否比仅执行onclick =&#39;bla()&#39;更好?为什么? - Javascript: is biding events using Jquery's bind() better than simply doing the onclick='bla()' and why? 有没有比这更好的方法来创建仅使用JavaScript的切换功能(根本没有JQuery)? - Is there a better way than this to create a toggle function just with JavaScript (no JQuery at all)? 与使用字符串相比,使用coffeescript / jQuery生成HTML的更好方法? - Better way to generate HTML using coffeescript / jQuery than using strings? 比javascript中的“切换”更好的方式 - Better way than “switch” in javascript 更好的方法是使用每个jquery - Better way to use jquery each 是否有比使用Javascript更好的方法来在2种不同样式之间进行切换 - Is there a better way to switch between 2 different styles than this using Javascript
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM