删除重复项后重建JSON

时间:2014-08-21 13:39:04

标签: javascript jquery json

我有以下JSON -

{  
   "node1":[  
      {  
         "one":"foo",
         "two":"foo",
         "three":"foo",
         "four":"foo"
      },
      {  
         "one":"bar",
         "two":"bar",
         "three":"bar",
         "four":"bar"
      },
      {  
         "one":"foo",
         "two":"foo",
         "three":"foo",
         "four":"foo"
      }
   ],
   "node2":[  
      {  
         "link":"baz",
         "link2":"baz"
      },
      {  
         "link":"baz",
         "link2":"baz"
      },
      {  
         "link":"qux",
         "link2":"qux"
      },

   ]
};

我有以下javascript将从node1部分删除重复项

function groupBy(items, propertyName) {
          var result = [];
          $.each(items, function (index, item) {
              if ($.inArray(item[propertyName], result) == -1) {
                  result.push(item[propertyName]);
              }
          });
          return result;
      }

groupBy(catalog.node1, 'one');

但是,这并不考虑node2中的重复项。

我需要的结果是看起来像 -

{  
   "node1":[  
      {  
         "one":"foo",
         "two":"foo",
         "three":"foo",
         "four":"foo"
      },
      {  
         "one":"bar",
         "two":"bar",
         "three":"bar",
         "four":"bar"
      }
   ],
   "node2":[  
      {  
         "link":"baz",
         "link2":"baz"
      },
      {  
         "link":"qux",
         "link2":"qux"
      },

   ]
};

但是我不能让它工作,而groupBy只返回一个删除了重复项的字符串而不是重构的JSON?

3 个答案:

答案 0 :(得分:2)

这是我的版本:

  var obj = {} // JSON object provided in the post.

  var result = Object.keys(obj);

  var test = result.map(function(o){  
      obj[o] = obj[o].reduce(function(a,c){
        if (!a.some(function(item){
                    return JSON.stringify(item) === JSON.stringify(c); })){
           a.push(c);
        } 
        return a; 
      },[]); return obj[o]; });

  console.log(obj);//outputs the expected result

使用 Array.prototype.reduce 以及 Array.prototype.some 我搜索了添加到Array.prototype.reduce中生成的新数组中的所有项目名为a的var通过执行:

a.some(function(item){ return JSON.stringify(item) === JSON.stringify(c); })

Array.prototype.some 将循环播放此新数组,并使用JSON.stringify将现有项与新项c进行比较。

答案 1 :(得分:2)

您应该寻找一些JavaScript set的良好实现,并使用它来表示您的节点对象。设置数据结构将确保您只保留唯一项目。

另一方面,您可以尝试编写自己的重复数据删除算法。这是一个例子

function dedup(data, equals){
    if(data.length > 1){
        return data.reduce(function(set, item){
            var alreadyExist = set.some(function(unique){
                return equals(unique, item);
            });
            if(!alreadyExist){
                set.push(item)
            }
            return set;
        },[]);
    }
    return [].concat(data);
}

不幸的是,这个算法的性能不太好,我觉得有点像O(n ^ 2/2),因为我每次检查一组唯一项目来验证给定项目是否存在。如果您的结构非常小,这将不会是一件大事。但无论如何,这是基于散列或基于树的算法可能更好的地方。

你还可以看到我已经抽象出了什么是"等于"的定义。所以你可以在辅助功能中提供它。很可能使用JSON.stringify是一个坏主意,因为序列化对象需要时间。如果您可以编写自己的自定义算法来按键比较键,那可能会更好。

所以,一个天真(不推荐)的equals实现可能有点像其他答案中提出的那样:

var equals = function(left, right){ 
  return JSON.stringify(left) === JSON.stringify(right); 
};

然后你可以这样做:

var res = Object.keys(source).reduce(function(res, key){
    res[key] = dedup(source[key], equals);
    return res;
},{});

答案 2 :(得分:0)

试试这个:

 var duplicatedDataArray = [];
    var DuplicatedArray = [];

    //Avoiding Duplicate in Array Datas
    var givenData = {givenDataForDuplication : givenArray};
    $.each(givenData.givenDataForDuplication, function (index, value) {
        if ($.inArray(value.ItemName, duplicatedDataArray) == -1) {
            duplicatedDataArray.push(value.ItemName);
            DuplicatedArray.push(value);
        } 
    });