Javascript 基于多个键值对搜索对象数组的优化方法
我编写了一个通用扩展方法,它将返回一个与所有给定搜索条件(lookUpArray)匹配的项。这是你的电话号码Javascript 基于多个键值对搜索对象数组的优化方法,javascript,algorithm,search,optimization,data-structures,Javascript,Algorithm,Search,Optimization,Data Structures,我编写了一个通用扩展方法,它将返回一个与所有给定搜索条件(lookUpArray)匹配的项。这是你的电话号码 /**********************扩展方法****************************/ var utils={}; //可以创建一个实用函数来执行此操作 utils.searchInArray=函数(lookUpArray、caseSensitiveSearch){ 如果(!lookUpArray | | lookUpArray.length这取决于您的用例。如
/**********************扩展方法****************************/
var utils={};
//可以创建一个实用函数来执行此操作
utils.searchInArray=函数(lookUpArray、caseSensitiveSearch){
如果(!lookUpArray | | lookUpArray.length这取决于您的用例。如果您将相当频繁地运行搜索功能(与修改数组的频率相比),如果要搜索的可能键数量有限,则可能会发现创建和维护一个类似索引的结构是值得的
操作,其中m
是键的数量,n
是数组中的项数。如果有适当的数据结构,查找可以变成O(m)
操作。因为我猜n
可能是目前为止最大的数字,这可能会使搜索规模更有效
如果这样做没有意义,那么你至少应该让你的内环短路
var self = this;
for (var index = 0; index < self.length; index++) {
var item = self[index];
var matches = true;
for (var i = 0; i < lookUpArray.length; i++) {
var lookUpItem = lookUpArray[i];
if (item[lookUpItem.key] !== lookUpItem.value) {
matches = false;
break;
}
}
if(matches) {
return item;
}
};
return null;
我建议不要将此方法添加到阵列原型中。我只是将其作为一种实用方法。您可以使用
阵列。查找函数
如果数组中有元素,find()方法将返回数组中的值
满足提供的测试函数。否则返回undefined
请看以下示例:
var inventory = [
{name: 'apples', quantity: 2},
{name: 'bananas', quantity: 0},
{name: 'cherries', quantity: 5}
];
function findCherries(fruit) {
return fruit.name === 'cherries';
}
console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }
您还可以编写自定义逻辑,例如查找素数:
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) {
return false;
}
}
return element > 1;
}
console.log([4, 6, 8, 12].find(isPrime)); // undefined, not found
console.log([4, 5, 8, 12].find(isPrime)); // 5
函数isPrime(元素、索引、数组){
var启动=2;
同时(开始1;
}
console.log([4,6,8,12].find(isPrime));//未定义,未找到
console.log([4,5,8,12].find(isPrime));//5
如果有帮助,请标记正确。您可以使用数组函数,如array.prototype.filter
和array.prototype.every
,而不是自己迭代项目:
var utils = {
searchInArray: function(targetArray, lookupArray, caseSensitiveSearch) {
return targetArray.filter(function(x) {
return lookupArray.every(function(lookup) {
if (x[lookup.key] === undefined)
throw new Error('No ' + lookup.key + ' property in object ' + x);
if (typeof x[lookup.key] !== typeof lookup.value)
throw new Error('Type mismatch on property ' + lookup.key ' + in object ' + x);
if (typeof lookup.value === 'string' && caseSensitiveSearch)
return x[lookup.key].toLowerCase() === lookup.value.toLowerCase();
else
return x[lookup.key] === lookup.value;
});
});
}
};
工作演示片段:
var utils={
searchInArray:函数(targetArray、lookupArray、caseSensitiveSearch){
返回targetArray.filter(函数(x){
返回lookupArray.every(函数(查找){
if(x[lookup.key]==未定义)
抛出新错误('No'+lookup.key+'对象'+x'中的属性);
if(typeof x[lookup.key]!==typeof lookup.value)
抛出新错误('属性'+lookup.key'+对象'+x'中的类型不匹配);
if(typeof lookup.value==='string'&&caseSensitiveSearch)
返回x[lookup.key].toLowerCase()==lookup.value.toLowerCase();
其他的
返回x[lookup.key]==lookup.value;
});
});
}
};
var inputObject数组=[
{emailType:'primary',id:1,用户名:'saurabh',电子邮件:'test@gmail.com,电话:'123'},
{emailType:'附加',id:2,电子邮件:'test2@gmail.com' },
{emailType:'附加',id:2,电子邮件:'test2@gmail.com,用户名:'spp'}
];
var lookUpArray=[{
关键字:“emailType”,
价值:'附加'
}, {
键:“id”,
价值:2
}];
var result=utils.searchInArray(inputObjectArray,lookUpArray,true);
console.log(result);
要获取第一个匹配的obj,您可以尝试以下方法
utils.searchInArray = function(lookUpArray, caseSensitiveSearch) {
if (!lookUpArray || lookUpArray.length <= 0)
return null;
caseSensitiveSearch = caseSensitiveSearch || true;
var self = this;
return self.find(function(obj) {
return lookUpArray.every(function(lookup) {
if (typeof lookup.value === 'string' && caseSensitiveSearch)
return obj[lookup.key].toLowerCase() === lookup.value.toLowerCase();
else
return obj[lookup.key] === lookup.value;
});
});
};
utils.searchInArray=函数(lookUpArray,caseSensitiveSearch){
如果(!lookUpArray | | lookUpArray.length,则内循环的大小写可能有中断
,或者如果向外循环添加外部:
标签,则会有继续外部
。此外,如果大小写是冗余的,则内循环的大小写不会更改存在的值
(除了第一次将true
更改为1
)之外。既然您希望提高性能,那么存储长度,而不是在每次迭代时检索长度;)为什么要优化性能?使用。某些()
函数会降低速度,不是吗?(与for
循环相比)@NNNN:可能会稍微慢一点,但如果没有基准,很难说。如果浏览器环境本机支持它(而不是polyfill),我可以想象它会稍微快一点。无论哪种方式,我通常认为最好集中在大规模的效率和可读性上,并且只有在绝对必要的时候才进行实质性的优化。内环短路会改变结果。如果(…!=…)中断,应该是(仍然使用exist
变量或一些等效项),因为目标是找到一个符合所有查找条件的项。@nnnnnnnn:很好!我想我已经修复了它。它现在看起来如何?“请随意更正我的代码”-完成。(冒号在后面,它必须在for的前面,而不是在它里面。有些人把它写在同一行上,比如outer:for(…)
)我不经常使用标签,但有时它们对嵌套循环很有帮助。问题很明显是关于一个通用方法,该方法覆盖对象数组中多个属性的匹配。除了没有实际解决问题外,还不清楚这是如何表示性能优化的。这使代码更整洁,但这是一个“优化”?对于
循环,使用那些带有回调的数组方法不会比慢吗?@nnnnnn公平地说,OP没有提到他们想要优化的内容。这个答案优化了结构(和可读性);-P
function isPrime(element, index, array) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) {
return false;
}
}
return element > 1;
}
console.log([4, 6, 8, 12].find(isPrime)); // undefined, not found
console.log([4, 5, 8, 12].find(isPrime)); // 5
var utils = {
searchInArray: function(targetArray, lookupArray, caseSensitiveSearch) {
return targetArray.filter(function(x) {
return lookupArray.every(function(lookup) {
if (x[lookup.key] === undefined)
throw new Error('No ' + lookup.key + ' property in object ' + x);
if (typeof x[lookup.key] !== typeof lookup.value)
throw new Error('Type mismatch on property ' + lookup.key ' + in object ' + x);
if (typeof lookup.value === 'string' && caseSensitiveSearch)
return x[lookup.key].toLowerCase() === lookup.value.toLowerCase();
else
return x[lookup.key] === lookup.value;
});
});
}
};
utils.searchInArray = function(lookUpArray, caseSensitiveSearch) {
if (!lookUpArray || lookUpArray.length <= 0)
return null;
caseSensitiveSearch = caseSensitiveSearch || true;
var self = this;
return self.find(function(obj) {
return lookUpArray.every(function(lookup) {
if (typeof lookup.value === 'string' && caseSensitiveSearch)
return obj[lookup.key].toLowerCase() === lookup.value.toLowerCase();
else
return obj[lookup.key] === lookup.value;
});
});
};
utils.searchInArray = function(lookUpArray, caseSensitiveSearch) {
if (!lookUpArray || lookUpArray.length <= 0)
return null;
caseSensitiveSearch = caseSensitiveSearch || true;
var self = this;
return self.filter(function(obj) {
return lookUpArray.every(function(lookup) {
if (typeof lookup.value === 'string' && caseSensitiveSearch)
return obj[lookup.key].toLowerCase() === lookup.value.toLowerCase();
else
return obj[lookup.key] === lookup.value;
});
});
};