![](/img/trans.png)
[英]Building an Object of arrays comparing two arrays using reduce
[英]Comparing Multiple Arrays Using Reduce
Javascript 非常新,我在大約一個月的時間里已經嘗試了這個問題大約 4 次,但我仍然無法解決它。
所以這里的問題是:構造一個函數交集,比較輸入數組並返回一個包含在所有輸入中找到的元素的新數組。 獎勵:使用減少!
格式為:
function intersection(arrays) {
// Your Code Goes Here
}
測試用例:應該記錄 [15, 5]
console.log('Extensions 3 Test: ' + intersection([5, 10, 15, 20], [15, 88, 1, 5, 7]/*, [1, 10, 15, 5, 20]*/));
我目前的解決方案:適用於只有兩個項目要比較的情況,但不適用於第三個項目,我可以這樣做,以便我可以循環遍歷並將獲得的值與下一個數組進行比較,但我認為我不是在正確的道路上......另外,我沒有使用 reduce 來實現它......而且我不確定我是否應該使用“參數”。 任何幫助表示贊賞! 非常感謝。
function intersection(arrays) {
array = [];
for (var i = 0; i < arguments.length; i++)
array.push(arguments[i]);
var result = [];
for(var i = 0; i < array.length - 1; i++) {
for(var j = 0; j < array[i].length; j++) {
if (array[i+1].includes(array[i][j]))
result.push(array[i][j]);
}
}
return result;
}
雖然幾個建議說,你可以使用下划線, lodash ,或者我個人的最愛, Ramda (免責聲明:我是作者之一),這個功能應該是簡單的,以至於你甚至不考慮它的庫。 這是一個簡單的版本:
const intersection = (xs, ys) => xs.filter(x => ys.indexOf(x) > -1);
intersection([5, 10, 15, 20, 3], [15, 88, 3, 1, 5, 7]); //=> [5, 15, 3]
const intersectAll = (...xss) => xss.reduce(intersection);
intersectAll([5, 10, 15, 20, 3], [15, 88, 3, 1, 5, 7], [1, 10, 15, 5, 20]); //=> [5, 15]
我認為這就是你所需要的,至少只要你只擔心引用/原始相等並且不需要考慮你想知道{x: 1}
和{x: 1}
是相同的,即使它們不是相同的參考。 如果確實需要,可以查看 Ramda 的intersection
函數。
請注意,如果includes
更好的支持,我會推薦這個版本,因為它讀起來更好:
const intersection = (xs, ys) => xs.filter(x => ys.includes(x));
此外,如果您不需要二元函數,您可以通過組合以上兩個來制作它的可變參數版本:
const intersection = (...xss) => xss.reduce((xs, ys) => xs.filter(x => ys.indexOf(x) > -1));
也許有人會發現它很有用。
作為函數的參數,您可以提供任意數量的任意長度的數組,並且該函數是緊湊的,我認為 ;)
const findSimilar = (...arrays) => { return arrays.reduce((includ, current) => Array.from(new Set(includ.filter((a) => current.includes(a)))) ); }; console.log( findSimilar([5, 10, 15, 20], [15, 88, 1, 5, 7], [1, 10, 15, 5, 20]) );
以及它是如何工作的:
好的,首先你將其余參數(...數組)作為函數的參數,所以你有
數組 = [ [5, 10, 15, 20], [15, 88, 1, 5, 7], [1, 10, 15, 5, 20] ]
然后在減少的第一次迭代中我們有
包括 = [5, 10, 15, 20] 和當前 = [15, 88, 1, 5, 7]
在這兩個上我們使用filter ,什么給了我們 [5,15],我使用Set使 shure 沒有重復並使數組返回( Array.from() ),它將作為“includ”傳遞給reduce的下一次迭代",在下一次迭代中,我們有
incude = [5,15] 和 current = [1, 10, 15, 5, 20] 等等......
我們甚至可以像這樣使用它
let result = [ [5, 10, 15, 20], [15, 88, 1, 5, 7], [1, 10, 15, 5, 20] ].reduce((includ, current) => Array.from(new Set(includ.filter((a) => current.includes(a)))) ); console.log(result);
雖然不能直接解決您的問題,但您可以使用開源庫underscore.js做您想做的事情。
_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]
您可以從實施的方式中獲得靈感。 以上是對它們自己的_.intersection
函數的函數調用,該函數也依賴於其他 underscore.js 函數,如下所示:
// Produce an array that contains every item shared between all the
// passed-in arrays.
_.intersection = function(array) {
if (array == null) return [];
var result = [];
var argsLength = arguments.length;
for (var i = 0, length = array.length; i < length; i++) {
var item = array[i];
if (_.contains(result, item)) continue;
for (var j = 1; j < argsLength; j++) {
if (!_.contains(arguments[j], item)) break;
}
if (j === argsLength) result.push(item);
}
return result;
};
這是使用reduce的解決方案,將空數組作為交集作為初始值傳入。
迭代數字並檢查每個數字是否出現在子數組之一中。
如果不是,請將布爾值 isPresentInAll 設置為 false。
如果它確實出現在所有三個中並且它還沒有出現在交集數組中,則推送到交集數組。
function intersection(arrayOfArrays) {
return arrayOfArrays.reduce(function(intersection, subArray) {
subArray.forEach(function(number) {
var isPresentInAll = true;
for (var i = 0; i < arrayOfArrays.length; i++) {
if (arrayOfArrays[i].indexOf(number) === -1) {
isPresentInAll = false;
}
}
if (isPresentInAll === true && intersection.indexOf(number) === -1) {
intersection.push(number);
}
});
return intersection;
}, []);
}
我想我得到了適合你的功能。 (注意:結果未排序!)
var intersection = function() {
// merge deduped arrays from arguments
var arrays = Array.prototype.reduce.call(arguments, function(carry, array) {
return [].concat(carry, array.filter(function(item, index, origin) {
return origin.indexOf(item) === index;
}));
}, []);
var results = arrays.reduce(function(carry, item, index, arr) {
if(
// just select items, which have more then 1 occurance
arr.filter(function(fItem) {
return fItem === item;
}).length > 1 &&
// ... and which are not already in results
!~carry.indexOf(item)
) {
carry = [].concat(carry,item);
}
return carry;
}, []);
return results;
};
這是一個使用 2 減少的版本。
第一個只迭代數組一次以創建一個 hashmap 對象來跟蹤實例計數,第二個返回計數與參數數量匹配的值
function intersection(){ // convert arguments to array of arrays var arrays = [].slice.call(arguments); // create an object that tracks counts of instances and is type specific // so numbers and strings would not be counted as same var counts= arrays.reduce(function(a,c){ // iterate sub array and count element instances c.forEach(function(val){ var propName = typeof val + '|' + val; // if array value not previously encountered add a new property a[propName] = a[propName] || {count:0, value: val}; // increment count for that property a[propName].count++; }); return a; },{}); // iterate above object to return array of values where count matches total arrays length return Object.keys(counts).reduce(function(resArr, propName){ if(counts[propName].count === arrays.length){ resArr.push(counts[propName].value); } return resArr; },[]); } console.log(intersection([5, 10, 15, 20], [15, 88, 1, 5, 7], [1, 10, 15, 5, 20]))
可以使用一些微調來確保有足夠的參數並且它們都是數組
這是我想出的使用 vanilla javascript 和一個減少調用的方法。
function intersection(){
var arrays = [].slice.call(arguments);
var first = arrays[0];
var rest = arrays.slice(1);
return first.reduce(function(all, item, index){
var push = rest.every(function(subArray){
return subArray.indexOf(item) > -1;
});
if(push){
all.push(item);
}
return all;
},[])
}
console.log(intersection([5, 10, 15, 20], [15, 88, 1, 5, 7], [1, 10, 15, 5, 20]));
function intersection(arrays) {
let common = arrays.reduce(function(accumulator, currentValue) {
return accumulator.filter(function(x){
return currentValue.indexOf(x) > -1;
})
})
return common;
}
為了優化不能在超過 2 個子數組上工作且未使用 reduce 的答案,這里的代碼適用於您傳入的多個子數組。
function intersection(arr1, arr2, arr3){
let ans = arr1[0]; // ans = [5,10,15,20]
for(let i = 0; i < ans.length; i++){ // i = 0...3
for(let j = 1; j < arr1.length; j++){ // j = 1...2
if(!(arr1[j].includes(ans[i]))){ // if the new subarray doesn't include an element in the ans
ans.splice(i, 1); // delete the element from ans
}
}
}
return ans;
}
const arr1 = [5, 10, 15, 20];
const arr2 = [15, 88, 1, 5, 7];
const arr3 = [1, 10, 15, 5, 20];
console.log(intersection([arr1, arr2, arr3])); // should log: [5, 15]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.