我有一个数组,其中一些元素是“重复”,我想删除数组中的重复。
因此,例如,左侧的列表(数组)变为右侧的数组:
Ingredients: Ingredients:
Apples Apples
Apples Oranges
Oranges Bananas
Oranges
Oranges
Bananas
这样做的好算法是什么?
现在这就是我的伪代码:
for each element in ingredients (counter j)
for each element-below-current-element (counter k)
if ingredients[i] == element-below-current-element[j]
splice (delete) ingredients[i]
现在问题是我注意到原始列表中是否有奇数数量的元素,那么我可能会得到这样的结果:
Ingredients: Ingredients:
Apples Apples
Oranges Oranges
Oranges Oranges
Oranges Bananas
Bananas
一切都有效,除了我可能会得到一种成分的双倍。
这是我的实际代码实现,在 javascript 中,并且包含一些角度元素(例如$ scope),但它并不重要。
for(var j = 0; j < $scope.groceryList.length; j++){
for(var k = j+1; k < $scope.groceryList.length; k++){ // for each of elements below current element (j)
if ( $scope.groceryList[j].name == $scope.groceryList[k].name){
$scope.groceryList.splice(k, 1);
}
}
}
现在我得到的是每当你移除一个数组元素时数组长度是如何减少的,这会导致你的计数器在下一次迭代时向前跳一个元素...
答案 0 :(得分:4)
Underscore.js
是我推荐用于在JavaScript中执行所有数组处理的工具(还有,就像,就像所有内容一样。非常棒。)
恰好它的uniq
方法将完全符合你的需要。
var myArray = ["Apples","Oranges","Oranges","Grapes","Apples"];
_.uniq(myArray);
//returns ["Apples","Oranges","Grapes"]
答案 1 :(得分:2)
在这种情况下,您通常无法使用for
循环进行内循环。 while
效果很好,但是:
for(var j = 0; j < $scope.groceryList.length; j++){
var k = j+1;
while(k < $scope.groceryList.length){ // each of elements below current element (j)
if ( $scope.groceryList[j].name == $scope.groceryList[k].name){
$scope.groceryList.splice(k, 1);
}
else {
++k;
}
}
}
如果您拼接,请不要增加k
。如果你不这样做,那就去做吧。
(我希望我的缩进是正确的,它不是我以前习惯的风格。)
答案 2 :(得分:1)
我只是对它进行排序,然后进行比较......
var arr = ["Apples","Oranges","Oranges","Grapes","Apples"];
var sorted_arr = arr.sort();
var results = [];
for (var i = 0; i < arr.length - 1; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
results.push(sorted_arr[i]);
}
}
alert(results);
答案 3 :(得分:1)
此代码是最简单的解决方案,但需要双倍的内存 - 对于示例中的小数据集而言不是问题。
Array.prototype.filterDuplicates = function () {
var filtered = [];
for (var i = 0; i < this.length; i++)
if (filtered.indexOf(this[i]) == -1)
filtered.push(this[i]);
return filtered;
}
答案 4 :(得分:1)
我最喜欢的方法是使用数组方法来保存代码:
arr1=[
"Apples",
"Apples",
"Oranges",
"Oranges",
"Oranges",
"Bananas"
];
var unq= arr1.filter(function unq(a,b,c){return c.indexOf(a)===b;});
alert(unq); // shows "Apples,Oranges,Bananas"
没有变量,没有工件,只有逻辑和结果。
编辑:更改为仅使用一个重复数组。 如果你想从另一个数组中过滤一个数组,只需将上面的“c.indexOf”更改为数组的var名称。
我更喜欢打破unq功能,所以我可以从任何地方调用.filter(unq)来获得一个独特的数组......
答案 5 :(得分:1)
线性时间,恒定空间算法:
不,我不能给你JavaScript。
示例:强>
输入:
Ingredients, Apples, Apples, Oranges, Oranges, Oranges, Bananas
有两个指数(一个快速和一个慢),都从零开始
fast
slow
V
Ingredients, Apples, Apples, Oranges, Oranges, Oranges, Bananas
增加两者直到我们前一个元素与当前元素相同。
fast
slow
V
Ingredients, Apples, Apples, Oranges, Oranges, Oranges, Bananas
快速增加直到它不同。
slow fast
V V
Ingredients, Apples, Apples, Oranges, Oranges, Oranges, Bananas
快速将元素设置为缓慢的元素。
slow fast
V V
Ingredients, Apples, Oranges, Oranges, Oranges, Oranges, Bananas
增加两者。
slow fast
V V
Ingredients, Apples, Oranges, Oranges, Oranges, Oranges, Bananas
增加快速值,直到与替换元素(橙子)不同
slow fast
V V
Ingredients, Apples, Oranges, Oranges, Oranges, Oranges, Bananas
快速将元素设置为缓慢的元素。
slow fast
V V
Ingredients, Apples, Oranges, Bananas, Oranges, Oranges, Bananas
增加两者。
slow fast
V V
Ingredients, Apples, Oranges, Bananas, Oranges, Oranges, Bananas
到了最后。
将列表缩短为慢。
Ingredients, Apples, Oranges, Bananas
答案 6 :(得分:0)
使用关联数组进行存在检查:
var exists = {}, i;
for (i = 0; i < arr.length; i += 1) {
if (exists[arr[i]]) {
arr.splice(i, 1);
i--;
} else {
exists[arr[i]] = true;
}
}
// arr should now have no dupes
答案 7 :(得分:0)
var ingredients = [
"Apples",
"Apples",
"Oranges",
"Oranges",
"Oranges",
"Bananas"
];
var uniqIngredients = {};
for (i in ingredients) {
uniqIngredients[ingredients[i]] = true;
}
ingredients = [];
for (i in uniqIngredients) {
ingredients.push(i);
}