三个阵列之间的联合

时间:2018-12-15 15:24:21

标签: javascript arrays function

我需要找到传递给函数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]

4 个答案:

答案 0 :(得分:4)

使用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);

答案 1 :(得分:4)

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

type
  TIntFuncArray := TArray<TFunc<Integer>>;
var
  A: TIntFuncArray;
begin
  A := TIntFuncArray.Create(MyFunc); // or maybe @ or Addr(), not sure
end;

或者更短(但对阅读的友好程度较低):

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

说明:

注意:[5, 10, 15, 15, 88, 1, 5, 7, 100, 15, 10, 1, 5]当前是一项实验性功能(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat)。不使用下面的平面的解决方案:

Array.flat

说明(仅与上面的区别):

  • 代替.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])); ,以便通过将新数组作为Array.concat并将其作为参数提供给this

摘要:http://jsfiddle.net/briosheje/y03osape/2/

不含[].concat.apply([],[...arrays])的代码段:http://jsfiddle.net/briosheje/y03osape/4/

答案 2 :(得分:1)

我试图复制您的遍历数组的方法,但是以稍微更有效的方式,仅使用ES5安全功能。我敢肯定,如果您可以使用其他答案的功能,那么其​​他答案会更有效。

this.books = this.store.pipe(select(selectVisibleBooks));

答案 3 :(得分:0)

基于练习中先前的自定义forEach和Reduce (在http://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函数,则可以删除空的初始数组要求。