【问题标题】:Union between three arrays三个数组之间的并集
【发布时间】:2018-12-15 15:24:20
【问题描述】:

我需要找到传递给函数union 的三个数组的并集。

我花了大约 50 行代码来获得预期的结果。显然,下面的代码有效,但现在我想知道做同样工作的最佳方法是什么(以功能和非功能方式)。

function union(...arrays) {
    var array1 = arguments[0];
    var array2 = arguments[1];
    var array3 = arguments[2];      

    var unique = [];
    var intersaction = [];

    // find the unique values

    for(let i = 0; i < array1.length; i++) {
        if( (array2.includes(array1[i]) == false) && (array3.includes(array1[i])) == false ) {
            unique.push(array1[i]); 
        }
    }

    for(let i = 0; i < array2.length; i++) {
        if( (array1.includes(array2[i]) == false) && (array3.includes(array2[i])) == false ) {
            unique.push(array2[i]); 
        }
    }

    for(let i = 0; i < array3.length; i++) {
        if( (array1.includes(array3[i]) == false) && (array2.includes(array3[i])) == false ) {
            unique.push(array3[i]);
        }
    }

    // find the intersection

    for(let j = 0; j < array1.length; j++) {
        if(array2.includes(array1[j]) || array3.includes(array1[j]) ) {
            if (intersaction.indexOf(array1[j]) == -1) { 
                intersaction.push(array1[j]);
            }
        }
    }

    for(let j = 0; j < array2.length; j++) {
        if(array1.includes(array2[j]) || array3.includes(array2[j]) ) {
            if (intersaction.indexOf(array2[j]) == -1) { 
                    intersaction.push(array2[j]);
            }       
        }
    }

    for(let j = 0; j < array3.length; j++) {
        if(array1.includes(array3[j]) || array2.includes(array3[j]) ) {
            if (intersaction.indexOf(array3[j]) == -1) { 
                    intersaction.push(array3[j]);
            }       
        }
    }

    return union = [...intersaction, ...unique];

}

console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));
// should log: [5, 10, 15, 88, 1, 7, 100]

【问题讨论】:

  • 您是否考虑过使用 sets 来代替?像这样的东西:jsfiddle.net/briosheje/y03osape/1Array.from(new Set([...arrays].flat()));
  • union 对您来说意味着什么?我希望[5, 15] 的结果。

标签: javascript arrays function


【解决方案1】:

保留 OP 提供的原始函数签名的另一种解决方案:

function union(...arrays) {
    return Array.from(new Set([...arrays].flat()));
}

console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));

或者,甚至更短(但阅读不友好):

return [...(new Set([...arrays].flat()))];

解释:

注意:Array.flat 目前是一个实验性功能 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat)。下面不使用平面的解决方案:

function union(...arrays) {
    return Array.from(new Set([].concat.apply([],[...arrays])));
}

console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));

说明(仅与上述不同):

  • 我们将 .flat 应用于 Array.concat 我们的原始数组,以便将其展平,传递一个新数组作为其 this 并提供我们的数组作为参数:[].concat.apply([],[...arrays])

片段:http://jsfiddle.net/briosheje/y03osape/2/

不带.flat的片段:http://jsfiddle.net/briosheje/y03osape/4/

【讨论】:

  • 我不建议任何人使用.flat(),因为它仍然是一个实验性的 api。
  • @kinduser 你是对的,确实。我会更新一个替代方案。
  • 改用[].concat(...arrays);
  • @kinduser 是的,遵循.apply 的方法,我个人更喜欢它。感谢您指出这一点。
【解决方案2】:

使用set,很简单,

Set 对象允许您存储任何类型的唯一值,无论是 原始值或对象

var a=  [5, 10, 15];
var b=[15, 88, 1, 5, 7];
var c=[100, 15, 10, 1, 5];
var result= [...new Set([...a, ...b,...c])];
console.log(result);

【讨论】:

    【解决方案3】:

    我试图复制你的循环数组的方法,但以一种更有效的方式,只使用 ES5 安全函数。如果您可以使用它们的功能,我相信其他答案会更有效。

    var a = [1, 2, 3];
    var b = [1, 2, 4, 5];
    var c = [2, 7, 9];
    
    // takes an array of arrays
    function getUnique(input) {
    
      var unique = [];
    
      // loop over each array
      input.forEach(function(item) {
        // loop over each value
        item.forEach(function(value) {
          // if it's not already in the unique array,
          if (unique.indexOf(value) == -1) {
            // add it
            unique.push(value);
          }
        });
      });
    
      return unique;
    }
    
    // takes an array of arrays
    function getIntersection(input) {
    
      // assume all elements in first array are common
      var intersection = input.shift();
      var remove = [];
    
      // loop over items in first array and attempt to
      // disprove commonality
      intersection.forEach(function(value) {
    
        // loop over subsequent arrays
        for (var i = 0; i < input.length; i++) {
          var item = input[i];
          // if these arrays don't contain the value, 
          // then it isn't an intersection
          if (item.indexOf(value) == -1) {
            // add it to an array to be removed
            remove.push(value);
            // exit this loop
            break;
          }
        }
      });
    
      // remove values determined not to be intersections
      remove.forEach(function(value) {
        intersection.splice(intersection.indexOf(value), 1);
      })
    
      return intersection;
    }
    
    
    var test = getUnique([a, b, c]);
    
    console.log(test);
    
    var test2 = getIntersection([a, b, c]);
    
    console.log(test2);

    【讨论】:

      【解决方案4】:

      基于之前练习中的自定义 forEach 和 Reducehttp://csbin.io/callbacks

      function forEach(array, callback) {
          for(i = 0; i < array.length; i++){
              callback(array[i])
          }
      }
      
      function reduce(array, callback, initialValue) {
          for(let i of array){
              initialValue = callback(initialValue, i)
          }
          return initialValue
      }
      
      function union(...arrays) {
          return reduce(arrays, (seen, next) => {
              forEach(next, (element) => {
                  if(!seen.includes(element)) seen.push(element);
              })
              return seen
          }, [])
      }
      

      请注意,如果您使用内置的 reduce 函数,您可以删除空的初始数组要求。

      【讨论】:

        猜你喜欢
        • 2023-03-18
        • 2017-01-04
        • 2013-02-25
        • 1970-01-01
        • 2021-09-10
        • 2013-11-17
        • 2019-01-20
        • 1970-01-01
        • 2021-08-26
        相关资源
        最近更新 更多