【问题标题】:Find duplicate value in array of objects and merge some duplicate key and value在对象数组中查找重复值并合并一些重复的键和值
【发布时间】:2015-12-11 09:49:31
【问题描述】:

我有两个对象数组

array = [
 {
  "id_0":356,
  "name":"India",
  "key1":150
 },
 {
  "id_0":356,
  "name":"India",
  "key2":200
 },
 {
  "id_0":748,
  "name":"Swaziland",
  "key1":140
 },
 {
  "id_0":748,
  "name":"Swaziland",
  "key2":180
 }
]

我正在尝试在对象数组中查找重复的id_0,并将key2 的重复对象和值合并。

我希望结果是:

array = [
 {
  "id_0":356,
  "name":"India",
  "key1":150,
  "key2":200
 },
 {
  "id_0":748,
  "name":"Swaziland",
  "key1":140,
  "key2":180
 }
]

如何找到重复值并将重复的键和值合并到数组中?

【问题讨论】:

  • nameIndia 变成india,另外,如果重复的属性相同,你期望它的结果是什么,例如,如果第一项也有key2: 123 ,结果会是什么?

标签: javascript arrays


【解决方案1】:

您可以根据需要使用Array.prototype.reduce() 来减少您的阵列。

可以使用Object.assign()合并重复项。

var array = [
    { 'id_0': 356, 'name': 'India', 'key1': 150 },
    { 'id_0': 356, 'name': 'India', 'key2': 200 }
];

var result = array.reduce(function(prev, item) {
    var newItem = prev.find(function(i) {
        return i.id_0 === item.id_0; 
    });
    if (newItem) {
        Object.assign(newItem, item);
    } else {
        prev.push(item);
    }
    return prev;
}, []);

console.log(result);

Object.assign 是 ES6 的一部分。如果它不适合您,只需将其替换为:

for (var attrname in item) {
    newItem[attrname] = item[attrname];
};

【讨论】:

    【解决方案2】:

    试试这个fiddle

    var array = [
     {
      "id_0":356,
      "name":"India",
      "key1":150
     },
     {
      "id_0":356,
      "name":"India",
      "key2":200
     },
     {
      "id_0":356,
      "name2":"china",
      "key2":200
     }
    ]
    function mergeArray( arr )
    {
       var outputObj = {};
       for ( var counter = 0; counter < arr.length; counter++ )
       {
          var obj = arr[ counter ];
          for( var key in obj )
          {
             if ( !outputObj[ key ] )
             {
               outputObj[ key ] = obj[ key ];
             }
          }
       }
       return outputObj;
    }
    console.log( mergeArray( array ) );
    

    编辑 fiddle 以满足您的“更新”要求

    var array = [
     {
      "id_0":356,
      "name":"India",
      "key1":150
     },
     {
      "id_0":356,
      "name":"India",
      "key2":200
     },
     {
      "id_0":400,
      "name2":"china",
      "key2":200
     },
     {
      "id_0":400,
      "name2":"china",
      "key2":200
     }
    ]
    function mergeArray( arr )
    {
       var outputObj = {};
       for ( var counter = 0; counter < arr.length; counter++ )
       {
          var obj = arr[ counter ];
          for( var key in obj )
          {
             if ( !outputObj[ key ] )
             {
               outputObj[ key ] = obj[ key ];
             }
          }
       }
       return outputObj;
    }
    function collateArray( arr )
    {
       var outputObj = {};
       var result = [];
       for ( var counter = 0; counter < arr.length; counter++ )
       {
          var obj = arr[ counter ];
          var id_0value = obj[ "id_0" ];
          if ( !outputObj[ id_0value ] )
          {
            outputObj[ id_0value ] = [];
          }
          outputObj[ id_0value ].push( obj );
       }
       console.log( outputObj );
       for ( var key in outputObj )
       {
          result.push( mergeArray( outputObj[ key ] ) );
       }
       return result;
    
    }
    console.log( collateArray( array ) );
    

    【讨论】:

    • @elango 对象之间共有的其他属性呢
    • 查看结果是按 id_0 分组,我有不同的 id_0 在对象数组中可用,所以我想按 id_0 分组
    【解决方案3】:

    使用一个临时的Object作为存储key =&gt; item的映射可以使时间复杂度达到O(n)

    var arr = [
     {
      "id_0":356,
      "name":"India",
      "key1":150
     },
     {
      "id_0":356,
      "name":"India",
      "key2":200
     },
     {
      "id_0":748,
      "name":"Swaziland",
      "key1":140
     },
     {
      "id_0":748,
      "name":"Swaziland",
      "key2":180
     }
    ];
    
    // items:            the array to be merged to unique.
    // attrName:    the attribute's name that is for distinguish,
    // isOverwrite:decides whether the value will be overwrite by later ones or not. Default to false. 
    function getUnique(items, attrName, isOverwrite) {
      // Map to keep reference to objects by its id.
      var store = {};
      // The array for output result.
      var result = [];
      
      isOverwrite = !!isOverwrite;
      
      items.forEach(function(item) {
        var id = item[attrName];
        var key;
        
        // Try to fetch item by id from store.
        var target = store[id];
        
        // If target item exist in store, its dulplicated, we need to merge it.
        if (typeof target !== 'undefined') {
          // If it's presented, we need to merge it into existing one.
          for (key in item) {
            if (!item.hasOwnProperty(key)) {
              continue;
            }
            
            // If isOverwrite is true, always use the newest value, otherwise,
            // we only apply values that are not exist in target yet.
            if (isOverwrite || typeof target[key] === 'undefined') {
              target[key] = item[key];
            }
          }
        } else {
          // If its not in store yet, put it a clone into result, and to map for 
          // later reference.
          var clone = {};
          for (key in item) {
            if (item.hasOwnProperty(key)) {
              clone[key] = item[key];
            }        
          }
          store[id] = clone;      
          // Also put it into the result array.
          result.push(clone);
       }
      });
    
      return result;
    }
    
    console.log(getUnique(arr, 'id_0'));

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-27
      • 1970-01-01
      • 2018-07-08
      • 2011-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多