数组是错误的数据结构。使用一些对象并预先设置索引,您根本不需要搜索。
我将假设id
每个客户的财产都是独一无二的。如果不是这样,请告诉我。
而且我要冒昧地使用getClientsMeetingCriteria()
(find
下面代码中的方法)。我将返回一个包含这些客户端的对象,而不是返回一个客户端数组。这主要是为了展示一个重要的观点:您实际上可以编写此代码,因此此检索是即时的。整个函数体很简单:
return criteria[criterion] || {};
如果您也需要一个简单的数组(并且仍然非常快),那么我们将回到这个问题。
将此代码粘贴到您的 Chrome 或 Firebug 控制台并执行它:
// Return a boolean telling if an object is empty (has no properties)
function isEmpty( object ) {
for( var name in object ) {
return false;
}
return true;
}
// An object that keeps track of clients and criteria (id_list)
function Clients() {
// An object containing all of the clients that have been added
// using clients.add(client). The client.id is the property name,
// and the client object is the property value. So:
// clients[clientID] is a client object with the given client.id
var clients = {};
// An object containing every unique criterion ID. The criterion ID
// is the property name, and the property value is an object
// containing every client that has this criterion ID in its id_list
// property. So:
// criteria[criterionID] is an object containing clients
// criteria[criterionID][clientID] is a client with that criterion
var criteria = {};
// Internal function to split an id_list and iterate over it
function eachCriterion( client, callback ) {
var ids = client.id_list.split(';');
for( var i = 0, n = ids.length; i < n; ++i ) {
callback( ids[i] );
}
}
// Add a client
this.add = function( client ) {
if( clients[client.id] ) {
// already exists, return or error?
}
clients[client.id] = client;
eachCriterion( client, function( id ) {
if( ! criteria[id] ) {
criteria[id] = {}
}
criteria[id][client.id] = client;
});
};
// Remove a client
this.remove = function( client ) {
delete clients[client.id];
eachCriterion( client, function( id ) {
delete criteria[id][client.id];
if( isEmpty(criteria[id]) ) {
delete criteria[id];
}
});
};
// Return an object containing all the clients that have the given
// criterion in their id_list property
this.find = function( criterion ) {
return criteria[criterion] || {};
};
}
var clients = new Clients;
var client3 = { id:3, id_list:'10;20' };
var client1 = { id:1, id_list:'30;40;10' };
var client4 = { id:4, id_list:'40;20' };
var client5 = { id:5, id_list:'50;70' };
var client9 = { id:9, id_list:'10;70' };
var client2 = { id:2, id_list:'50;' };
var client7 = { id:7, id_list:'40;70;90' };
clients.add( client3 );
clients.add( client1 );
clients.add( client4 );
clients.add( client5 );
clients.add( client9 );
clients.add( client2 );
clients.add( client7 );
function find( id ) {
console.log( 'Finding', id );
console.log( JSON.stringify( clients.find(id), null, 4 ) );
}
find( '10' );
clients.remove( client3 );
find( '10' );
clients.remove( client1 );
find( '10' );
clients.remove( client9 );
find( '10' );
它将记录:
Finding 10
{
"1": {
"id": 1,
"id_list": "30;40;10"
},
"3": {
"id": 3,
"id_list": "10;20"
},
"9": {
"id": 9,
"id_list": "10;70"
}
}
Finding 10
{
"1": {
"id": 1,
"id_list": "30;40;10"
},
"9": {
"id": 9,
"id_list": "10;70"
}
}
Finding 10
{
"9": {
"id": 9,
"id_list": "10;70"
}
}
Finding 10
{}
如果你真的需要一个数组而不是一个对象来.find()
返回,你可以使用这个版本的find
方法来代替(或任何类似的代码):
this.find = function( criterion ) {
var result = [];
for( var id in criteria[criterion] ) {
result.push( clients[id] );
}
return result;
};