[英]Finding intersection between 2 arrays of objects with dynamic keys
我有 2 個帶有動態鍵的對象數組(我從不知道鍵的名稱); 例子:
hierarchy1: [
{
level1: 'Shoes',
}
]
hierarchy2: [
{
level1: 'Shoes',
level2: 'Sneakers',
},
]
我需要找到hierarchy1和hierarchy2之間的交集。 我不能使用 lodash _.intersectionBy 因為我不知道我將在hierarchy1中獲得的密鑰的名稱。
我希望得到這樣的結果 [{ level1: 'Shoes' }] 任何想法如何解決這個問題?
非常感謝!
如果你想與每個索引進行比較,那么你可以做這樣的事情
const hierarchy1 = [{ level1: 'Shoes', level3: "xyz" }] const hierarchy2 = [{ level1: 'Shoes', level2: 'Sneakers', }, { level3: "xyz" }] function intersection(arr1, arr2) { let final = [] // loop over first array for (let i = 0; i < arr1.length; i++) { let element = arr1[i] let temp = {} // loop over all indexes of second array for (let data of arr2) { // check every key fro data to see if there's any intersection Object.keys(data).forEach(key => { if (data[key] === element[key] && key in element) { temp[key] = element[key] } }) } // if we found any intersection push it in final array if (Object.keys(temp).length) { final.push(temp) } } return final } console.log(intersection(hierarchy1, hierarchy2))
對第一種方法的改進是進行一些預先計算,您可以簡單地將特定鍵的所有值組合在一起,並且在循環時您可以檢查給定鍵是否存在特定值
const hierarchy1 = [{ level1: 'Shoes', level3: "xyz" },{level2: "abc"}] const hierarchy2 = [{ level1: 'Shoes', level2: 'Sneakers', }, { level3: "xyz", level2: "abc" }] function intersection(arr1, arr2) { let final = [] let map = {} for(let data of arr2){ Object.keys(data).forEach(key => { map[key] = map[key] || new Set() map[key].add(data[key]) }) } // loop over first array for (let i = 0; i < arr1.length; i++) { let element = arr1[i] let temp = {} Object.keys(element).forEach(key => { if (key in map && map[key].has(element[key])) { temp[key] = element[key] } }) // if we found any intersection push it in final array if (Object.keys(temp).length) { final.push(temp) } } return final } console.log(intersection(hierarchy1, hierarchy2))
如果您只想比較各自的索引或兩個數組,您可以執行以下操作
const hierarchy1 = [{ level1: 'Shoes', }] const hierarchy2 = [{ level1: 'Shoes', level2: 'Sneakers', },] function intersection(arr1,arr2){ let final = [] for(let i=0; i<arr1.length; i++){ let element = arr1[i] let temp = {} Object.keys(element).forEach(key => { if(key in arr2[i] && arr2[i][key] === element[key]){ temp[key] = element[key] } }) if(Object.keys(temp).length){ final.push(temp) } } return final } console.log(intersection(hierarchy1,hierarchy2))
您可以使用接受多個數組的_.intersectionWith()
和一個比較器函數來比較兩個項目。 要找到匹配的鍵,我們可以在兩個對象的鍵之間使用_.intersection()
,然后使用Array.some()
找到兩個對象中至少一個具有匹配值的鍵。
const intersectionWithDynamicKeys = (arr1, arr2) => _.intersectionWith( arr1, arr2, (o1, o2) => _.union(_.keys(o1), _.keys(o2)) .some(key => o1[key] === o2[key]) ) // Finds [{ level1: 'Shoes' }] console.log(intersectionWithDynamicKeys( [{ level1: 'Shoes' }], [{ level1: 'Shoes', level2: 'Sneakers' }] )) // Finds [{ level1: 'Shoes' }] but doesn't find { level2: 'Sneakers' console.log(intersectionWithDynamicKeys( [{ level1: 'Shoes' }, { level2: 'Sneakers' }], [{ level1: 'Shoes', level2: 'Sneakers' }] ))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
使用_.intersectionWith()
的主要警告是,一旦項目匹配,它就不會再次使用。 因此,例如,如果您有
const arr1 = [{ level1: 'Shoes' }, { level2: 'Sneakers' }],
const arr2 = [{ level1: 'Shoes', level2: 'Sneakers' }]
只有{ level1: 'Shoes' }
因為{ level1: 'Shoes', level2: 'Sneakers' }
不會用於與{ level2: 'Sneakers' }
進行比較,因為找到了匹配項。
如果要查找具有匹配鍵的所有對象,則需要將一個數組中的所有對象與另一個數組中的所有對象進行比較。 為此,請過濾第一個數組。 使用Array.some()
迭代第二個數組。 獲取所有唯一鍵(使用Set
),然后嘗試在兩個對象中找到至少一個具有相同值的鍵。
注意:沒有匹配一次限制,第一個數組中的多個對象可以與第二個數組中的單個對象匹配。
const getUniqueKeys = (o1, o2) => [...new Set([...Object.keys(o1), ...Object.keys(o2)])] const intersectionWithDynamicKeys = (arr1, arr2) => arr1.filter(o1 => arr2.some(o2 => getUniqueKeys(o1, o2) .some(key => o1[key] === o2[key]) ) ) // Finds [{ level1: 'Shoes' }, { level2: 'Sneakers' }] console.log(intersectionWithDynamicKeys( [{ level1: 'Shoes' }, { level2: 'Sneakers' }], [{ level1: 'Shoes', level2: 'Sneakers' }] )) // Finds [{ level1: 'Shoes' }, { level2: 'Sneakers' }, { level2: 'Sneakers' }] console.log(intersectionWithDynamicKeys( [{ level1: 'Shoes' }, { level2: 'Sneakers' }, { level2: 'Sneakers' }], [{ level1: 'Shoes', level2: 'Sneakers' }] ))
您可以使用它來稍微重塑它。
var all = [...hierarchy1, ...hierarchy2].map(c=> Object.entries(c)).flat()
/*
[
[ 'level1', 'Shoes' ],
[ 'level1', 'Shoes' ],
[ 'level2', 'Sneakers' ]
]
*/
然后把它變成你想要的任何格式
all.reduce((a,[key,value])=>({
...a,
[key]: a[key]?a[key]+1:1
}),{})
/*
{ level1: 2, level2: 1 }
*/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.