Javascript - 关于HashTable的澄清

时间:2018-01-27 20:53:25

标签: javascript duplicates

我正在观看视频,了解如何创建一个函数来替换数组中的所有重复项。例如,如果数组由[1,1,2]组成,则该函数将仅输出[1,2]。

观看视频后,最终代码为:

let removeDuplicates = (a)=>{

let input = {};
let output = [];

for (let i = 0; i < a.length; i++){
    let el = a[i];

    if (!(el in input)){
        input[el] = true;
        output.push(el)
    }
  };
  return output;
}

我理解大部分功能,但我在if语句中无法理解HashTable输入的使用方式。我的问题是 1)我们如何检查输入中的el是否为输入以前从未在函数中使用过。 2)为什么我们设置输入[el] = true。

对不起,如果这不是世界上最明显的问题。我无法理解这个问题。在此先感谢您的帮助。

4 个答案:

答案 0 :(得分:1)

  1. input在for循环之外声明,因此它存在于函数之前,并且在整个过程中仍然存在于for循环范围内。 More info about the let keyword and its scoping
  2. 我们可以设置任意值,只需el
  3. 中的input键即可

答案 1 :(得分:1)

input从空{}开始,然后在第一个循环看起来像{"1": true}之后,在第二个循环后,没有任何变化,在第三个循环看起来像{"1": true, "2": true}之后

即使我们将代码更改为以下任何一项,代码仍然有效:

input[el] = undefined;
input[el] = null;
input[el] = el;
input[el] = "blah";
input[el] = "";
input[el] = false;
input[el] = 0;

因为input包含键“1”,所以值1将永远不会多次添加到output数组中。处理此问题的测试也可以从以下更改:

if (!(el in input)){

为:

if( !input.hasOwnProperty(el) ) {

请参阅:Object.prototype.hasOwnProperty

您还可以在for循环结束时记录输入内容,看看发生了什么:

console.log(JSON.stringify(input));

我使用JSON.stringify来避免任何“有用的”浏览器控制台更新以前记录的对象的内容。

基本上,玩代码看看会发生什么。如果您只读过如何编码,那么您将永远无法编码。

以下是您可以运行/修改以查看其工作原理的代码片段:

let a = [1, 1, 2];

let input = {};
let output = [];

console.log(JSON.stringify(input));

for (let i = 0; i < a.length; i++){
    let el = a[i];

    if (!(el in input)){
    //if (input.hasOwnProperty(el))){
        input[el] = true;
        //input[el] = undefined;
        //input[el] = null;
        //input[el] = el;
        //input[el] = "blah";
        //input[el] = "";
        //input[el] = false;
        //input[el] = 0;
        output.push(el)
    }
    
    console.log(JSON.stringify(input));
}

console.log(output);

并且为了完整性,您还可以通过简单地执行以下操作来消除伪哈希input对象(尽管对于大型数组,性能方面可能要慢得多):

let a = [1, 1, 2];
let output = [];

for (let i = 0; i < a.length; i++){
    if (output.indexOf(a[i]) === -1 ){
        output.push(a[i])
    }
}

console.log(JSON.stringify(output)); // [1,2]

答案 2 :(得分:0)

  1. 基本上,代码使用input变量来保存已经在传递的a数组中迭代的所有值。 Input从空开始,并在我们通过a进行迭代时填充。它在for循环的范围内。

  2. 代码集input[el] = true,但实际上您可以将input[el]设置为任何内容并让代码仍然有效。所有条件!(el in input)都在检查输入是否有一个键为el的对象。在这种情况下,该密钥的值无关紧要。

  3. 使用a is [1,1,2] ...

    中的示例

    首先将input对象设为空。

    然后,您接受a1的第一个元素,并设置el = 1

    如果1不在input(不是),则设置input[1] = true,然后将1推到output数组。

    接下来,您接受第二个元素1并设置el = 1

    此时

    !(el in input)为false,因为1已经在input对象中。你忽略了这一点并继续a中的下一个元素。

    最后,检查2并设置el = 2。如果2不在input(不是),则设置input[2] = true,然后将2推到output数组。

    更直接的方法是将数组转换为集合。

    或者,您可以使用output数组并对传入的indexOf变量的每个元素使用a方法,看看它是否已存在于输出中 - 如果不存在,添加它。否则继续。

答案 3 :(得分:0)

好问题,其他人可能会问同样的事情。实际上,一旦你理解了它的工作原理,你的第二个问题就会回答你的第一个问题,所以让我们从那里开始。

2)要理解的第一件事是我们关心的是返回的输出数组没有任何重复,所以我们设置input [el] = true,因为我们希望这发生。通过if检查的任何值都会添加到输入对象,然后添加到我们所需的输出。在这种情况下,输入的行为类似于HashTable或Set:

1)通过这种理解,我们可以看到输入对象是在循环之外但在函数内声明的,所以它的全部目的只是一个容器(Set),在我们添加之前通过if检查来检查我们输出的一个项目。

这可以通过以下方式测试:

let input = {};
input["One"] = true;
console.log(input); //outputs {One: true}