【问题标题】:How to merge two arrays in JavaScript and de-duplicate items如何在 JavaScript 中合并两个数组并删除重复项
【发布时间】:2010-12-07 17:58:15
【问题描述】:

我有两个 JavaScript 数组:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

我希望输出是:

var array3 = ["Vijendra","Singh","Shakya"];

输出数组应该删除了重复的单词。

如何在 JavaScript 中合并两个数组,以便按照插入原始数组的相同顺序从每个数组中获取唯一项?

【问题讨论】:

  • 在发布新答案之前,请考虑此问题已有 75 多个答案。请确保您的答案提供的信息不在现有答案中。
  • [...new Set([...[1, 2, 3], ...[2, 3, 4]])] 结果 [1, 2, 3, 4]
  • 如果您想要一个更通用的解决方案,也涵盖深度合并,请查看at this question。一些答案也涵盖了数组。
  • TL;dr - 合并数组ba):a=a.concat(b); 从数组 a 中删除重复项(在-地点):a=a.filter((i,p)=>a.indexOf(i)===p);

标签: javascript arrays merge


【解决方案1】:

这是我的解决方案https://gist.github.com/4692150,具有深度相等且易于使用的结果:

function merge_arrays(arr1,arr2)
{
   ... 
   return {first:firstPart,common:commonString,second:secondPart,full:finalString}; 
}

console.log(merge_arrays(
[
[1,"10:55"] ,
[2,"10:55"] ,
[3,"10:55"]
],[
[3,"10:55"] ,
[4,"10:55"] ,
[5,"10:55"]
]).second);

result:
[
[4,"10:55"] ,
[5,"10:55"]
]

【讨论】:

    【解决方案2】:

    之前出于同样的原因写过(适用于任意数量的数组):

    /**
     * Returns with the union of the given arrays.
     *
     * @param Any amount of arrays to be united.
     * @returns {array} The union array.
     */
    function uniteArrays()
    {
        var union = [];
        for (var argumentIndex = 0; argumentIndex < arguments.length; argumentIndex++)
        {
            eachArgument = arguments[argumentIndex];
            if (typeof eachArgument !== 'array')
            {
                eachArray = eachArgument;
                for (var index = 0; index < eachArray.length; index++)
                {
                    eachValue = eachArray[index];
                    if (arrayHasValue(union, eachValue) == false)
                    union.push(eachValue);
                }
            }
        }
    
        return union;
    }    
    
    function arrayHasValue(array, value)
    { return array.indexOf(value) != -1; }
    

    【讨论】:

      【解决方案3】:
      Array.prototype.pushUnique = function(values)
      {
          for (var i=0; i < values.length; i++)
              if (this.indexOf(values[i]) == -1)
                  this.push(values[i]);
      };
      

      试试:

      var array1 = ["Vijendra","Singh"];
      var array2 = ["Singh", "Shakya"];
      array1.pushUnique(array2);
      alert(array1.toString());  // Output: Vijendra,Singh,Shakya
      

      【讨论】:

        【解决方案4】:

        如果你像我一样需要支持旧版浏览器,这适用于 IE6+

        function es3Merge(a, b) {
            var hash = {},
                i = (a = a.slice(0)).length,
                e;
        
            while (i--) {
                hash[a[i]] = 1;
            }
        
            for (i = 0; i < b.length; i++) {
                hash[e = b[i]] || a.push(e);
            }
        
            return a;
        };
        

        http://jsperf.com/merge-two-arrays-keeping-only-unique-values/22

        【讨论】:

          【解决方案5】:

          这很简单,可以用jQuery在一行中完成:

          var arr1 = ['Vijendra', 'Singh'], arr2 =['Singh', 'Shakya'];
          
          $.unique(arr1.concat(arr2))//one line
          
          ["Vijendra", "Singh", "Shakya"]
          

          【讨论】:

          • 来自 jQuery 文档“请注意,这仅适用于 DOM 元素数组,而不适用于字符串或数字。” (api.jquery.com/jQuery.unique)。该方法已被弃用。
          【解决方案6】:

          我在尝试做同样的事情时遇到了这篇文章,但我想尝试一些不同的事情。我只是做了下面的功能。我还有另一个变量“compareKeys”(键数组)用于进行浅对象比较。以后我可能会把它改成一个函数。

          无论如何,我没有包括那部分,因为它不适用于问题。我还将我的代码放入了 jsperf 中。编辑:我在 jsperf 中修复了我的条目。与 140k 相比,我的函数获得大约 99k ops/sec。

          代码:我首先创建一个可用索引的数组,然后通过迭代第一个数组来消除它们。最后,我通过使用两个数组之间不匹配的精简索引数组来推入“剩余”。

          http://jsperf.com/merge-two-arrays-keeping-only-unique-values/26

          function indiceMerge(a1, a2) {
              var ai = [];
              for (var x = 0; x < a2.length; x++) {
                  ai.push(x)
              };
          
              for (var x = 0; x < a1.length; x++) {
                  for (var y = 0; y < ai.length; y++) {
                      if (a1[x] === a2[ai[y]]) {
                          ai.splice(y, 1);
                          y--;
                      }
                  }
              }
          
              for (var x = 0; x < ai.length; x++) {
                  a1.push(a2[ai[x]]);
              }
          
              return a1;
          }
          

          【讨论】:

          • 这有什么不同?
          • 我写它时考虑到了性能。有很多方法可以做 OP 想要的,但性能通常被忽略。三年后,您可以查看link 以获取更新。 @djechlin
          【解决方案7】:

          用法:https://gist.github.com/samad-aghaei/7250ffb74ed80732debb1cbb14d2bfb0

          var _uniqueMerge = function(opts, _ref){
              for(var key in _ref)
                  if (_ref && _ref[key] && _ref[key].constructor && _ref[key].constructor === Object)
                    _ref[key] = _uniqueMerge((opts ? opts[key] : null), _ref[key] );
                  else if(opts && opts.hasOwnProperty(key))
                    _ref[key] = opts[key];
                  else _ref[key] = _ref[key][1];
              return _ref;
          }
          

          【讨论】:

            【解决方案8】:

            最好和最简单的方法是使用 JavaScript 的函数“some()”,它返回 true 或 false,指示数组是否包含对象的元素。你可以这样做:

            var array1 = ["Vijendra","Singh"]; 
            var array2 = ["Singh", "Shakya"];
            
            var array3 = array1;
            
            array2.forEach(function(elementArray2){
                var isEquals = array1.some(function(elementArray1){
                    return elementArray1 === elementArray2;
                })
                if(!isEquals){
                    array3.push(elementArray2);
                }
            });
            console.log(array3);
            

            结果:

            ["Vijendra", "Singh", "Shakya"]
            

            ss 你想要的......不要重复它......

            【讨论】:

            • “ss you wish”是什么意思?
            【解决方案9】:
            var a = [1,2,3]
            var b = [1,2,4,5]
            

            我喜欢一个班轮。这会将不同的 b 元素推送到 a

            b.forEach(item => a.includes(item) ? null : a.push(item));
            

            还有一个不会修改的版本

            var c = a.slice();
            b.forEach(item => c.includes(item) ? null : c.push(item));
            

            【讨论】:

              【解决方案10】:

              如果你纯粹使用underscore.js,它没有unionWith、unionBy

              你可以试试: _.uniq(_.union(arr1, arr2), (obj) =&gt; obj.key) (key 是每个对象的关键参数) 这应该有助于在两个数组合并后获得唯一性。

              【讨论】:

                【解决方案11】:

                我认为这会更快。

                removeDup = a => {
                
                    for (let i = a.length - 1; i >= 0; i--) {
                        for (let j = i-1; j >= 0; j--) {
                            if (a[i] === a[j])
                                a.splice(j--, 1);
                        }
                    }
                
                    return a;
                }
                

                【讨论】:

                  【解决方案12】:
                     //1.merge two array into one array
                  
                     var arr1 = [0, 1, 2, 4];
                     var arr2 = [4, 5, 6];
                  
                     //for merge array we use "Array.concat"
                  
                     let combineArray = arr1.concat(arr2); //output
                  
                     alert(combineArray); //now out put is 0,1,2,4,4,5,6 but 4 reapeat
                  
                     //2.same thing with "Spread Syntex"
                  
                     let spreadArray = [...arr1, ...arr2];
                  
                     alert(spreadArray);  //now out put is 0,1,2,4,4,5,6 but 4 reapete
                  
                  
                     /*
                         if we need remove duplicate element method use are
                         1.Using set
                         2.using .filter
                         3.using .reduce
                     */
                  

                  【讨论】:

                    【解决方案13】:

                    如果您有非常大的列表,则性能不佳,并且这不适用于合并,因为已经记录了许多解决方案,但是我用这个解决方案解决了我的问题(因为大多数数组过滤解决方案都适用于简单数组)

                    const uniqueVehiclesServiced = 
                      invoice.services.sort().filter(function(item, pos, ary) {
                        const firstIndex = invoice.services.findIndex((el, i, arr) => el.product.vin === item.product.vin)
                    
                      return !pos || firstIndex == pos;
                    });
                    

                    【讨论】:

                      【解决方案14】:

                      这是我在需要合并(或返回)两个数组时使用的函数。

                      var union = function (a, b) {
                        for (var i = 0; i < b.length; i++)
                          if (a.indexOf(b[i]) === -1)
                            a.push(b[i]);
                        return a;
                      };
                      
                      var a = [1, 2, 3, 'a', 'b', 'c'];
                      var b = [2, 3, 4, 'b', 'c', 'd'];
                      
                      a = union(a, b);
                      //> [1, 2, 3, "a", "b", "c", 4, "d"]
                      
                      var array1 = ["Vijendra", "Singh"];
                      var array2 = ["Singh", "Shakya"];
                      
                      var array3 = union(array1, array2);
                      //> ["Vijendra", "Singh", "Shakya"]
                      

                      【讨论】:

                        【解决方案15】:
                        function set(a, b) {
                          return a.concat(b).filter(function(x,i,c) { return c.indexOf(x) == i; });
                        }
                        

                        【讨论】:

                          【解决方案16】:

                          大输入的更好选择是对数组进行排序。然后合并它们。

                          function sortFunction(a, b) {
                                  return a - b;
                          }
                          
                          arr1.sort(sortFunction);
                          arr2.sort(sortFunction);
                          
                          function mergeDedup(arr1, arr2) {
                          
                              var i = 0, j = 0, result = [];
                              while (i < arr1.length && j < arr2.length) {
                          
                                  if (arr1[i] < arr2[j]) {
                                      writeIfNotSameAsBefore(result, arr1[i]);
                                      i++;
                                  }
                                  else if (arr1[i] > arr2[j]) {
                                      writeIfNotSameAsBefore(result, arr2[j]);
                                      j++;
                                  }
                                  else {
                                      writeIfNotSameAsBefore(result, arr1[i]);
                                      i++;
                                      j++;
                                  }
                          
                              }
                          
                              while (i < arr1.length) {
                                  writeIfNotSameAsBefore(result, arr1[i]);
                                  i++;
                              }
                          
                              while (j < arr2.length) {
                                  writeIfNotSameAsBefore(result, arr2[j]);
                                  j++;
                              }
                              return result;
                          }
                          
                          function writeIfNotSameAsBefore(arr, item) {
                              if (arr[arr.length - 1] !== item) {
                                  arr[arr.length] = item;
                              }
                              return arr.length;
                          }
                          

                          排序需要 O(nlogn + mlogm),其中 n 和 m 是数组的长度,合并需要 O(x),其中 x = Max(n, m);

                          【讨论】:

                            【解决方案17】:

                            您可以合并结果并过滤重复项:

                            let combinedItems = [];
                            
                            // items is an Array of arrays: [[1,2,3],[1,5,6],...]    
                            items.forEach(currItems => {
                                if (currItems && currItems.length > 0) {
                                    combinedItems = combinedItems.concat(currItems);
                                }
                            });
                            
                            let noDuplicateItems = combinedItems.filter((item, index) => {
                                return !combinedItems.includes(item, index + 1);
                            });
                            

                            【讨论】:

                              【解决方案18】:

                              /**
                               * De-duplicate an array keeping only unique values.
                               * Use hash table (js object) to filter-out duplicates.
                               * The order of array elements is maintained.
                               * This algorithm is particularly efficient for large arrays (linear time).
                               */
                              function arrayUniqueFast(arr) {
                              	var seen = {};
                              	var result = [];
                              	var i, len = arr.length;
                              	for (i = 0; i < len; i++) {
                              		var item = arr[i];
                              		// hash table lookup
                              		if (!seen[item]) {
                              			result.push(item);
                              			seen[item] = true;
                              		}
                              	}
                              	return result;
                              }
                              
                              ///// test
                              var array1 = ["Vijendra", "Singh"];
                              var array2 = ["Singh", "Shakya"];
                              
                              var result = arrayUniqueFast(array1.concat(array2));
                              document.write('<br>result: ' + result);

                              对于其他方法对数组进行去重,请参阅我的基准测试:https://jsperf.com/de-duplicate-an-array-keeping-only-unique-values

                              【讨论】:

                                【解决方案19】:

                                这速度很快,可以整理任意数量的数组,并且可以处理数字和字符串。

                                function collate(a){ // Pass an array of arrays to collate into one array
                                    var h = { n: {}, s: {} };
                                    for (var i=0; i < a.length; i++) for (var j=0; j < a[i].length; j++)
                                        (typeof a[i][j] === "number" ? h.n[a[i][j]] = true : h.s[a[i][j]] = true);
                                    var b = Object.keys(h.n);
                                    for (var i=0; i< b.length; i++)
                                        b[i]=Number(b[i]);
                                    return b.concat(Object.keys(h.s));
                                }
                                
                                > a = [ [1,2,3], [3,4,5], [1,5,6], ["spoon", "fork", "5"] ]
                                > collate( a )
                                
                                [1, 2, 3, 4, 5, 6, "5", "spoon", "fork"]
                                

                                如果不需要区分5和“5”,那么

                                function collate(a){
                                    var h = {};
                                    for (i=0; i < a.length; i++) for (var j=0; j < a[i].length; j++)
                                        h[a[i][j]] = typeof a[i][j] === "number";
                                    for (i=0, b=Object.keys(h); i< b.length; i++)
                                        if (h[b[i]])
                                            b[i]=Number(b[i]);
                                    return b;
                                }
                                [1, 2, 3, 4, "5", 6, "spoon", "fork"]
                                

                                会的。

                                如果您不介意(或更喜欢)所有值都以字符串结尾,那么就这样吧:

                                function collate(a){
                                    var h = {};
                                    for (var i=0; i < a.length; i++)
                                        for (var j=0; j < a[i].length; j++)
                                            h[a[i][j]] = true;
                                    return Object.keys(h)
                                }
                                ["1", "2", "3", "4", "5", "6", "spoon", "fork"]
                                

                                如果您实际上并不需要数组,而只是想收集唯一值并对其进行迭代,那么(在大多数浏览器(和 node.js)中):

                                h = new Map();
                                for (i=0; i < a.length; i++)
                                    for (var j=0; j < a[i].length; j++)
                                        h.set(a[i][j]);
                                

                                这可能更可取。

                                【讨论】:

                                • 非常感谢。在同步 jQuery 操作中,这是对内联生成数组有用的变体。
                                【解决方案20】:

                                我学会了一个用扩展运算符连接两个数组的小方法:

                                var array1 = ['tom', 'dick', 'harry'];
                                var array2 = ['martin', 'ricky'];
                                
                                array1.push(...array2);
                                

                                “...”扩展运算符将以下数组拆分为单个项目,然后 push 可以将它们作为单独的参数处理。

                                【讨论】:

                                • 有趣,但比 .concat() 可读性差,并且不能解决重复问题
                                【解决方案21】:

                                给定两个没有重复的简单类型的排序数组,这将在 O(n) 时间内将它们合并,并且输出也将被排序。

                                function merge(a, b) {
                                    let i=0;
                                    let j=0;
                                    let c = [];
                                    for (;;) {
                                        if (i == a.length) {
                                            if (j == b.length) return c;
                                            c.push(b[j++]);
                                        } else if (j == b.length || a[i] < b[j]) {
                                            c.push(a[i++]);
                                        } else {
                                            if (a[i] == b[j]) ++i;   // skip duplicates
                                            c.push(b[j++]);
                                        }
                                    }
                                }
                                

                                【讨论】:

                                • 这与接受的答案和其他几行大约 20 行原始 JS 答案有什么不同?
                                • @djechlin 它是不同的,因为正如我在描述中所说,它采用“简单类型的排序数组”并且它非常好,因为它是可移植的并且 O(n) 比答案 O 更快(n^2)。但不用担心。我不反对投反对票!
                                【解决方案22】:

                                const merge(...args)=&gt;(new Set([].concat(...args)))

                                【讨论】:

                                • 当然,如果你想返回一个数组,那么只需使用 Array.from(merge(arguments))
                                【解决方案23】:

                                用途:

                                Array.prototype.merge = function (arr) {
                                    var key;
                                    for(key in arr) 
                                        this[key] = arr[key];
                                };
                                

                                【讨论】:

                                • 这不会合并数组——这只是用另一个覆盖一个。例如,var f = [1]; f.merge([2]);
                                • 嗯...但我认为已经存在的键仍然存在,您希望新的键和合并的键覆盖?哦,也许我在想字典什么的。
                                【解决方案24】:

                                取两个数组a和b

                                var a = ['a','b','c'];
                                
                                var b = ['d','e','f'];
                                var c = a.concat(b); 
                                
                                
                                //c is now an an array with: ['a','b','c','d','e','f']
                                

                                【讨论】:

                                • 哪些浏览器支持concat
                                • @chovy - concat 是一种旧方法,来自 ECMAScript 3。使用它应该没有任何问题。请参阅兼容性表on the MDN
                                • 不符合去重标准
                                • 这个答案是从stackoverflow.com/questions/3975170/…复制过来的
                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 2017-06-22
                                • 2013-02-02
                                • 2017-06-05
                                • 1970-01-01
                                • 2012-02-26
                                相关资源
                                最近更新 更多