我需要找到传递给函数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]
答案 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]));
说明:
return [...(new Set([...arrays].flat()))];
以Iterable作为参数,这将从原始数组创建一个新数组。Array.from
将数组(参数)散布为一个新的单一数组(因此它成为数组的数组)-> [...arrays]
变为:[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]]
使数组变平,使得值的数组而不是值数组的ar数组-> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat-> .flat
变成[[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]
从数组中删除重复项并返回Iterable https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set。 -> new Set
成为一个Set实例(一个Iterable),没有重复项。然后,Array.from将Set(可迭代)转换为常规数组。这里的更多信息:How to convert Set to Array? 注意:[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
说明(仅与上面的区别):
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函数,则可以删除空的初始数组要求。