简体   繁体   English

Javascript代码无限循环

[英]Javascript code infinite loop

I'm making a function, which takes an array of values and returns an array with only unique values. 我正在创建一个函数,它接受一个值数组并返回一个只有唯一值的数组。 For example: 例如:

var strings = ["audi", "audi", "bmw", "bmw","bmw","bmw","audi","audi", "8-()"];

Result should be: 结果应该是:

alert( unique(strings) ); // audi, bmw, 8-()

I don't understand why my function goes into infinite loop, could anyone help please? 我不明白为什么我的功能进入无限循环,有人可以帮忙吗? Here is the function: 这是功能:

function unique(arr) {
   var result = [];
   result.push(arr[0]);

   for (var i = 1; i < arr.length; i++) {
       for (var j = 0; j < result.length; j++) {
           if  (result[j] != arr[i]) {
              result.push(arr[i]); 
           }
       }
   }

   return result;
} 

There is no need for nested loop. 不需要嵌套循环。 you can check the result for available values with Array.prototype.indexOf or Array.prototype.includes methods. 您可以使用Array.prototype.indexOfArray.prototype.includes方法检查结果的可用值。

 var strings = ["audi", "audi", "bmw", "bmw", "bmw", "bmw", "audi", "audi", "8-()"]; function unique(arr) { var result = []; result.push(arr[0]); for (var i = 1; i < arr.length; i++) { if (result.indexOf(arr[i]) === -1) result.push(arr[i]); } return result; } console.log(unique(strings)) 

BTW chef suggest is: BTW厨师建议:

 var strings = ["audi", "audi", "bmw", "bmw", "bmw", "bmw", "audi", "audi", "8-()"]; console.clear(); var result = strings.filter(function(s){ return this[s] ? false : (this[s] = true); }, Object.create(null)) console.log(result); 

You can make it very simpler with Set and spread operators belongs to ES6, 使用Setspread operators属于ES6,你可以使它更简单,

var unique = src => [...new Set(src)]

By the way your logic is wrong. 顺便说一句,你的逻辑错了。 It will not run into an infinite loop. 它不会遇到无限循环。 But it will give you an undesirable result. 但它会给你一个不良的结果。

You can make it simpler: using Array.reduce 您可以更简单:使用Array.reduce

 var values = [1,2,3,4,5,5,5,5,5,6,6,6,62,2,2] function getUniq(array) { return array.reduce(function(u, value) { if (u.indexOf(value) < 0) u.push(value) return u; }, []) } console.log(getUniq(values)) 

You can reduce the time complexity of this 您可以减少此时间的复杂性

var strings = ["audi", "audi", "bmw", "bmw","bmw","bmw","audi","audi", "8-()"];

var unique = [];

strings.forEach(function(str){
  if (unique.indexOf(str) < 0) {
     unique.push(str)
  }
});

return unique;

You can use Set also 您也可以使用Set

var strings = ["audi", "audi", "bmw", "bmw","bmw","bmw","audi","audi", "8-()"];
var uniq = new Set(strings);

// if you need in array 
uniq = Array.from(uniq);

You could also use a dictionary/hashtable for this. 您也可以使用字典/哈希表。 Then the total runtime should be O(N) for looping through arr once: 然后总运行时应该是O(N),用于循环arr一次:

function unique(arr) {
    unique = {}
    for(var i=0; i<arr.length; i++) {
        unique[arr[i]]=true
    }
    return Object.keys(unique)
}   

JSFiddle 的jsfiddle

You could change the inner loop a bit and use a variable found for checking if the value is in the result array. 您可以稍微更改内部循环并使用found的变量来检查值是否在结果数组中。

This variable is also needed to check if the value is to push to the result set. 还需要此变量来检查值是否要推送到结果集。

Additionally you could use a break to exit the inner loop if a duplicate value is found. 此外,如果找到重复值,您可以使用break来退出内部循环。

 function unique(arr) { var result = [], found; result.push(arr[0]); for (var i = 1; i < arr.length; i++) { found = false; // initial set to false for (var j = 0; j < result.length; j++) { if (result[j] === arr[i]) { found = true; // set to true to skip push break; // exit loop } } found || result.push(arr[i]); // push only, if not found } return result; } var strings = ["audi", "audi", "bmw", "bmw", "bmw", "bmw", "audi", "audi", "8-()"]; console.log(unique(strings)); // audi, bmw, 8-() 

A shorter ES6 proposal with Array#filter and a hash table as closure. 一个较短的ES6提案,带有Array#filter和一个哈希表作为闭包。

 function unique(arr) { return arr.filter((temp => a => !temp[a] && (temp[a] = true))(Object.create(null))); } var strings = ["audi", "audi", "bmw", "bmw", "bmw", "bmw", "audi", "audi", "8-()"]; console.log(unique(strings)); // audi, bmw, 8-() 

another fastest way, it is taking 2 milli seconds check the performance 另一种最快的方法,就是花2毫秒检查性能

var dupEleArr = [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 20, 3, 3, 3, 32, 324, 5, 52];
var uniqueArr = dupEleArr.sort(function(a,b){
    return a-b;
}).filter(function(ele,i,arr){
   return arr.length > 3 ? arr[i] != arr[i+1] : (arr.length == 2) ? (arr[i] != arr[i+1]) : true;
});

check jsfiddle 检查jsfiddle

push() Pushes a new object to the beginning of an array and pushes everything back! push()将一个新对象推送到数组的开头并将所有内容推回去!

Let's view the state of your arrays in the program: 让我们在程序中查看数组的状态:

arr = [A,B]    result = [A]    i = 1

j = 0 -> arr[i] = B and result[j] = A    
so we use push: result = [B,A] and j++

j = 1 -> arr[i] = B and result[j] = A
so we use push: result = [B,B,A] and j++

j = 2 -> arr[i] = B and result[j] = A
so we use push: result = [B,B,B,A] and j++

Your array keeps increasing and the check will never fail, since you append to the beginning of your array and not the end. 您的数组不断增加,检查永远不会失败,因为您追加到数组的开头而不是结尾。

But even if you appended your new Item to the end, you would not get unique results, since you have to check every element in result and only if not any of the results is the same you should add your new element to the result array. 但即使您将新项目添加到最后,也不会得到唯一的结果,因为您必须检查结果中的每个元素,并且只有在没有任何结果相同的情况下才应将新元素添加到结果数组中。

For better solutions see the other answers -> Use a Set with contains() 为了更好的解决方案看其他的答案- >使用设置contains()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM