有没有比for(for())更快的方法来找到多维数组中的值并返回其所有索引?

时间:2018-08-28 16:41:29

标签: javascript multidimensional-array

我需要找到二维数组的值并返回其索引。例如,如果我搜索的术语在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()找到更好的算法吗?为了公平地进行性能测试,如果要比较结果,请将搜索到的术语重新放置在算法数组中最坏情况的位置。

(目标是网站,所以所有常见的浏览器都应该支持它)

2 个答案:

答案 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");