我需要找到二维数组的值并返回其索引。例如,如果我搜索的术语在array [i] [j]中,那么我想返回[i,j]。
自然,我想出了一个简单的解决方案:
function find(str){
for(let o = 0; o < array.length; o++){
for(let k = 0; k < array[o].length; k++){
if(array[o][k] == str){
return [o, k];
}
}
}
}
现在,作为算法的一部分,我需要使用这种方法数百次,并且它的时间成本很高。有没有更有效的方法?
我创建了一个简单的完整示例,其中包含“基准”:
// setup to hide foo in an array
var array = [];
for(let i = 0; i < 100; i++){
array.push([])
for(let j = 0; j < 100; j++){
if(i == 99 && j == 99) array[i].push("foo"); // intentionally hiding the searched term at the worst-case position for the algorithm of find()
else array[i].push("bar");
}
}
// function to find foo
function find(str){
for(let o = 0; o < array.length; o++){
for(let k = 0; k < array[o].length; k++){
if(array[o][k] == str){
return [o, k];
}
}
}
}
// lets say we need to find foo 200 times
var a = window.performance.now();
for(let i = 0; i < 200; i++){
console.log(i, find("foo")); // if you're happy and you know it, tell us what you found
}
var b = window.performance.now();
// print performance result
$('body').html((b-a) + " ms");
JSfiddle作为基准示例:http://jsfiddle.net/3t0db1cq/11/
(注意:在该基准示例中,我搜索了'foo'200次,因此您可能会问为什么我不简单地对其进行缓存。实际上,我将搜索不同的术语,因此缓存几乎不能提高性能。确实将搜索到的字词置于此基准的数组的最坏情况下)
您能帮我为find()
找到更好的算法吗?为了公平地进行性能测试,如果要比较结果,请将搜索到的术语重新放置在算法数组中最坏情况的位置。
(目标是网站,所以所有常见的浏览器都应该支持它)
答案 0 :(得分:2)
在我看来,您正在将一个键(一对整数)映射到一个字符串值,并且您想返回该值的键。
在使用数组时,每次搜索操作总是O(n ^ 2),更糟糕的情况是,没有使用该数据结构的“智能”方法
正如@Richrd所说,您可以建立从字符串值到一对整数的反向映射,然后进行搜索。简单的方法是使用JavaScript Map()(哈希映射)。尽管您可能想研究字符串到整数映射的trie实现。
但是,这引出了一个问题:如果您要执行很多反向查询,那么为什么要首先将这些数据存储为2D字符串数组?首先,将这些数据存储为字符串到整数的映射,可以节省更多时间。
答案 1 :(得分:0)
如果您熟悉SQL,执行此操作的一种方法是使用sqllite。这是在浏览器中运行sql的非常简单的方法。
https://www.tutorialspoint.com/html5/html5_web_sql.htm
不幸的是,并非所有浏览器都支持该功能,因此您必须对受众有一个总体了解。
或者,只要所有值都不同,就可以反向映射数组,然后免费搜索任意数量的内容。例如:
// setup to hide foo in an array
var array = [];
for(let i = 0; i < 100; i++){
array.push([])
for(let j = 0; j < 100; j++){
if(i == 99 && j == 99) array[i].push("foo"); // intentionally hiding the searched term at the worst-case position for the algorithm of find()
else array[i].push("bar");
}
}
//Create your reverse mapped array. This only runs once at startup, but now allows you to
function buildReverse(arr) {
var reverseArr = {};
for(let o = 0; o < arr.length; o++){
for(let k = 0; k < arr[o].length; k++){
reverseArr[arr[o][k]] = [o, k];
}
}
return reverseArr
}
var reverseArr = buildReverse(array);
function find(str){
if (reverseArr[str] != undefined) {
return reverseArr[str];
// or
//return [reverseArr[str][0], reverseArr[str][1]]
//, etc...
}
return "";
}
// lets say we need to find foo 200 times
var a = window.performance.now();
for(let i = 0; i < 200; i++){
console.log(i, find("foo")); // if you're happy and you know it, tell us what you found
}
var b = window.performance.now();
// print performance result
$('body').html((b-a) + " ms");