【问题标题】:Reconstruct JSON after duplicates have been removed删除重复项后重建 JSON
【发布时间】:2014-08-21 13:39:03
【问题描述】:

我有以下 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 中的重复。

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

{  
   "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?

【问题讨论】:

    标签: javascript jquery json


    【解决方案1】:

    您可能应该寻找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;
    },{});
    

    【讨论】:

    • Spot on 是一种享受,运行时对我来说并不是真正的问题,因为它是我正在运行的小型数据集。结构良好且内容丰富的答案 +1。
    【解决方案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.reduceArray.prototype.some 我搜索了所有要添加到新数组中的项目,这些新数组生成到 var 中的 Array.prototype.reduce通过这样做命名a

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

    Array.prototype.some 将循环遍历这个新数组,并使用JSON.stringify 将现有项与新项c 进行比较。

    【讨论】:

    • 我理解你的逻辑,但是这是错误的 - 0x800a01b6 - JavaScript 运行时错误:对象不支持属性或方法“键”我认为在 IE8 中使用键时 htis 与之相关但我正在使用IE11??我也在 Chrome 中尝试过它只带回 [object][object]
    • 这与 ES5 兼容,这意味着它可以与 IE9+ 一起使用,如果您需要它与早期版本一起使用,您需要按照此处的建议进行 polyfill:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    【解决方案3】:

    试试这个:

     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);
            } 
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-31
      • 2019-08-08
      • 1970-01-01
      • 2018-04-07
      • 1970-01-01
      • 2021-05-07
      • 2013-06-09
      • 2016-01-05
      相关资源
      最近更新 更多