jQuery多维数组去重

3
我想用 jQuery 在我的数组中删除重复项。
该数组:
[[["Time",0],["Budget",1],["Scope",2],["Technical",3],["Budget",1]]]

如果在此示例中出现多次名称(“Budget”),则我想删除该值对。
我已经尝试了很多但迄今为止都没有成功。我尝试遍历数组并设置一个重复变量,然后将没有重复项的项目添加到新数组中。
  var items       = new Array ();
// get the data with ajax request
 $.ajax({
                url : "localhost/..",
                dataType : 'json',
                success: function(data) {

for (var prop_name in data.items) {
                    var duplicate = 0;
                    var count = 0;

// count how often the value appears
for (i = 0; i < data.items.length; i++) {
                    if (data.items[prop_name] == data.items[i]){
                        var count = count+1               
                        }
                }
// if there are duplicates, just add the value once
for (i = 0; i < items.length; i++) {    
                if (data.items[prop_name] == data.items[i]){
                duplicate = duplicate+1;
                    }
                if (duplicate <= 1){
                        items.push([ data.items[prop_name], count]) 
                    }
                duplicate = 0;
            }
}

你确定 data.items 是一个数组的数组的数组吗?看起来你多了一对方括号。你能提供 console.log(JSON.stringify(data.items)) 的输出以确保这一点吗? - trincot
是的,抱歉,在最后它再次被推入一个数组中。因为jqplot(制作图表)需要那种数据格式。 - simplesystems
3个回答

3

看下面的例子。你不能直接使用indexOf或者$.inArray

$ar=[["Time",0],["Budget",1],["Scope",2],["Technical",3],["Budget",1]];
$finalAr = [];
for($i=0;$i<$ar.length;$i++){
 $currentPair = $ar[$i];
  $pos = null;
  for($j=0;$j<$finalAr.length;$j++){
   if($finalAr[$j][0] == $currentPair[0] &&$finalAr[$j][1] == $currentPair[1]){
     $pos = $j;
    }
  }
  if($pos == null){
   $finalAr.push($currentPair);
  }
}
for($i=0;$i<$finalAr.length;$i++){
  $("#result").append($finalAr[$i][0]+"-->"+$finalAr[$i][1]+"<br/>");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result"></div>


我知道这已经老旧了,但是太棒了! - lazoDev

3
jQuery在这项任务中并不必要。还要注意,创建一个新数组与从现有数组中删除元素是不同的。
创建一个新数组: 简单地记录之前迭代过的“键”,可以防止重复被复制。

Using ES5's Array.prototype.filter makes this a trivial task:

var data = [["abc", 1], ["def", 2], ["ghi", 3], ["abc", 4], ["jkl", 5]];
var prev = {};

var filteredData = data.filter( function(arr) {

  var key = arr[0];

  if (prev[key])
    return false;

  return (prev[key] = true);
});

console.log(filteredData);
Note: There is always a time vs space trade off with algorithms. This hash lookup takes 1 unit of time vs a nested loop's n units of time (each element of the array), per array item. The hash storage takes up memory, while the loop doesn't.

对于小数据集,这不重要,但对于更大的数据集,这是需要考虑的事情。
删除元素: 否则,您将不得不在发现它们时删除副本。 Array.prototype.splice 可以从数组中删除元素。
*可能会遇到性能问题,但如果数据在客户端上管理,则仍有更大的问题需要解决。

1
你代码中的问题在于你这样比较数组:
 data.items[prop_name] == data.items[i]

等式的两侧都代表数组,即使它们的内容可能相同,它们也没有引用同一个数组。因此,除非prop_name === i,否则该等式将对所有元素失败,导致所有元素的计数为1。

举个例子,这将输出false

console.log(["Budget",1] == ["Budget",1]);

此外,您的数组在算法中嵌套更深,因此需要在主循环中处理 data.items[0]
我建议您使用数组函数来实现您想要的功能,并使用临时对象来注册每个字符串的计数,这样您就不必在循环内部循环。
您可以使用 filter 来实现这一点,并提供 thisArg 参数,以便我们可以使用 this 对象来保持遇到的名称的计数:
var items = [data.items[0].filter(function (pair) {
    return (this[pair[0]] = (this[pair[0]] || 0) + 1) === 1;
}, {})];

var data = {};
data.items = [[["Time",0],["Budget",1],["Scope",2],["Technical",3],["Budget",1]]];

var items = [data.items[0].filter(function (pair) {
    return (this[pair[0]] = (this[pair[0]] || 0) + 1) === 1;
}, {})];

console.log('before: ', data.items);
console.log('after: ', items);

这段代码仅比较成对字符串中的部分。如果可能有这样的数组:
[[["Time",0],["Time",1]]];

如果你想消除第二对,那么上面的解决方案将会实现这一点。但是如果你想在数字部分不同的情况下保留两者,则需要进一步调整代码:
var items = [data.items[0].filter(function (pair) {
    return (this[pair[0]+pair[1]] = (this[pair[0]+pair[1]] || 0) + 1) === 1;
}, {})];

注意:你并不真正需要jQuery来完成这个任务。

感谢您的详细解释!console.log(["Budget",1] == ["Budget",1])是返回false,但我不明白为什么会这样。对于(i = 0; i < data.items.length; i ++),如果(data.items [prop_name] == data.items [i]),则会起作用,然后计数器会加1。 - simplesystems
因为它引用了相同的数组? - simplesystems
实际上,它将完全针对每个元素工作一次,这是当循环获取值为prop_namei时:在那种情况下,您正在比较相同 的数组。请注意,在任何时候比较都不会查看数组内容。比较的是数组引用。当两者引用相同的内存位置时,它们相等。 - trincot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接