[英]Merging multiple arrays in javascript?
我有這段代碼應該根據匹配的siteid
合並 3 個數組。
這在一定程度上起作用。 基本上,它只找到 1 個站點 ID 並忽略相同的站點 ID!
這是代碼:
如果您運行下面的代碼,您會看到它只將siteid 為 77的表單之一添加到合並的數組中! 但它應該將所有具有相同站點 ID(在本例中為 77)的表單添加到合並數組中。
var siteS1 = [{
Date: '2021-02-02 11:19',
siteid: 77,
},
{
Date: '2021-02-02 11:19',
siteid: 76,
},
{
Date: '2021-02-02 11:19',
siteid: 66,
},
{
Date: '2021-02-02 11:19',
siteid: 96,
}
];
var siteS2 = [{
Date: '2021-02-02 11:19',
siteid: 77,
},
{
Date: '2021-02-02 11:19',
siteid: 76,
},
{
Date: '2021-02-02 11:19',
siteid: 66,
},
{
Date: '2021-02-02 11:19',
siteid: 96,
}
];
var form = [{
data: {},
siteid: 77,
},
{
data: {},
siteid: 77,
},
{
data: {},
siteid: 77,
},
{
data: {},
siteid: 96,
}
];
const merge = (...arrayList) => {
const siteids = arrayList
.map(array => array.map(item => item.siteid))
.flat()
return Array.from(new Set(siteids))
}
const find = (siteid, array) => {
const found = array.find(item => item.siteid === siteid)
if (!found) return undefined // returns undefined if item was not found
const {
siteid: _,
...restFoundData
} = found // omit `siteid` from found item
return restFoundData
}
const populate = (siteids) => siteids.map(siteid => {
const foundSiteS1 = find(siteid, siteS1)
const foundSiteS2 = find(siteid, siteS2)
const foundForm = find(siteid, form)
return {
siteS1: foundSiteS1,
siteS2: foundSiteS2,
form: foundForm ? [foundForm.data] : [], // empty array if no items matched
}
})
const result = populate(merge(siteS1, siteS2, form))
console.log(result)
我在這里缺少什么?
編輯:
這是示例代碼:
var siteS1 = [{
Date: '2021-02-02 11:19',
siteid: 77,
}];
var siteS2 = [{
Date: '2021-02-02 11:19',
siteid: 77,
}];
var form = [{
data: {},
siteid: 77,
},
{
data: {},
siteid: 77,
},
{
data: {},
siteid: 77,
},
{
data: {},
siteid: 77,
},
{
data: {},
siteid: 78,
}];
預期的結果是這樣的:
[{
"siteS1": {
"Date": "2021-02-02 11:19"
},
"siteS2": {
"Date": "2021-02-02 11:19"
},
"form": [{},{},{},{}]
}]
但是當前代碼的結果是這樣的:
[{
"siteS1": {
"Date": "2021-02-02 11:19"
},
"siteS2": {
"Date": "2021-02-02 11:19"
},
"form": [{}]
}]
如您所見,它只找到了 1 個站點 ID 為 77 的表單,而忽略了其余表單。
Array.find
查找第一個匹配元素,我使用另一個函數查找表單的所有匹配數據
const findAll = (siteid, array) => {
return array.filter(item => item.siteid === siteid).map(({siteid, ...data}) => data);
}
var siteS1 = [{ Date: '2021-02-02 11:19', siteid: 77, }, { Date: '2021-02-02 11:19', siteid: 76, }, { Date: '2021-02-02 11:19', siteid: 66, }, { Date: '2021-02-02 11:19', siteid: 96, } ]; var siteS2 = [{ Date: '2021-02-02 11:19', siteid: 77, }, { Date: '2021-02-02 11:19', siteid: 76, }, { Date: '2021-02-02 11:19', siteid: 66, }, { Date: '2021-02-02 11:19', siteid: 96, } ]; var form = [{ data: {}, siteid: 77, }, { data: {}, siteid: 77, }, { data: {}, siteid: 77, }, { data: {}, siteid: 96, } ]; const merge = (...arrayList) => { const siteids = arrayList .map(array => array.map(item => item.siteid)) .flat() return Array.from(new Set(siteids)) } const find = (siteid, array) => { const found = array.find(item => item.siteid === siteid) if (!found) return undefined // returns undefined if item was not found const { siteid: _, ...restFoundData } = found // omit `siteid` from found item return restFoundData } const findAll = (siteid, array) => { return array.filter(item => item.siteid === siteid).map(({siteid, ...data}) => data); } const populate = (siteids) => siteids.map(siteid => { const foundSiteS1 = find(siteid, siteS1) const foundSiteS2 = find(siteid, siteS2) const foundForm = findAll(siteid, form) return { siteS1: foundSiteS1, siteS2: foundSiteS2, form: foundForm, // empty array if no items matched } }) const result = populate(merge(siteS1, siteS2, form)) console.log(result)
所以這里有一些事情......
首先讓我們從兩個數組中獲取匹配的站點 ID:
const ids = [
...siteS1.map(({ siteid }) => siteid),
...siteS2.map(({ siteid }) => siteid),
].filter((x, i, arr) => arr.indexOf(x) !== i); // non-unique, i.e. in both arrays
好的,現在我們需要form
的條目:
const results = ids.map(id => {
return {
siteS1: {
Date: siteS1.find(({ siteid }) => siteid === id).Date,
},
siteS2: {
Date: siteS2.find(({ siteid }) => siteid === id).Date,
}
form: form.filter(({ siteid }) => siteid === id),
};
});
這將為您提供數組中兩個數組中每個站點 id 的結果。
最簡單的處理方法是按 id 創建地圖,以便您可以輕松查找數據。 這樣您就不會不斷地循環遍歷數組,試圖找到所有匹配的東西。
var siteS1 = [{ Date: '2021-02-02 11:19', siteid: 77, }, { Date: '2021-02-02 11:19', siteid: 76, }, { Date: '2021-02-02 11:19', siteid: 66, }, { Date: '2021-02-02 11:19', siteid: 96, } ]; var siteS2 = [{ Date: '2021-02-02 11:19', siteid: 77, }, { Date: '2021-02-02 11:19', siteid: 76, }, { Date: '2021-02-02 11:19', siteid: 66, }, { Date: '2021-02-02 11:19', siteid: 96, } ]; var form = [{ data: {}, siteid: 77, }, { data: {}, siteid: 77, }, { data: {}, siteid: 77, }, { data: {}, siteid: 96, } ]; const keyBySiteIdDate = (sites) => sites.reduce((acc, site) => { acc[site.siteid] = site.Date; return acc; }, {}); const keyBySiteIdData = (sites) => sites.reduce((acc, site) => { acc[site.siteid] = acc[site.siteid] || []; acc[site.siteid].push(site.data); return acc; }, {}); const sitesKeyed1 = keyBySiteIdDate(siteS1); const sitesKeyed2 = keyBySiteIdDate(siteS2); const dataKeyed = keyBySiteIdData(form); // as an array const result = Object.entries(sitesKeyed1).map(([siteId, date]) => { if (sitesKeyed2[siteId]) { return { siteId, siteS1: date, siteS2: sitesKeyed2[siteId], form: dataKeyed[siteId] || [], } } return null; }).filter(Boolean); console.log(result); // as an object const result2 = Object.entries(sitesKeyed1).reduce((acc, [siteId, date]) => { if (sitesKeyed2[siteId]) { acc[siteId] = { siteS1: date, siteS2: sitesKeyed2[siteId], form: dataKeyed[siteId] || [], } } return acc; }, {}); console.log(result2);
這假設值在兩個數組中。 如果它們可以在一個或另一個中並且您需要該數據,則循環會更多一些,但它是可行的。
var siteS1 = [{ Date: '2021-02-02 11:19', siteid: 77, }, { Date: '2021-02-02 11:19', siteid: 76, }, { Date: '2021-02-02 11:19', siteid: 66, }, { Date: '2021-02-02 11:19', siteid: 96, } ]; var siteS2 = [{ Date: '2021-02-02 11:19', siteid: 77, }, { Date: '2021-02-02 11:19', siteid: 76, }, { Date: '2021-02-02 11:19', siteid: 66, }, { Date: '2021-02-02 11:19', siteid: 96, }, { Date: '2021-02-02 11:19', siteid: 11111111111, } ]; var form = [{ data: {}, siteid: 77, }, { data: {}, siteid: 77, }, { data: {}, siteid: 77, }, { data: {}, siteid: 96, } ]; const keyBySiteIdDate = (sites) => sites.reduce((acc, site) => { acc[site.siteid] = site.Date; return acc; }, {}); const keyBySiteIdData = (sites) => sites.reduce((acc, site) => { acc[site.siteid] = acc[site.siteid] || []; acc[site.siteid].push(site.data); return acc; }, {}); const sitesKeyed1 = keyBySiteIdDate(siteS1); const sitesKeyed2 = keyBySiteIdDate(siteS2); const dataKeyed = keyBySiteIdData(form); const uniqueSiteIds = Array.from(new Set([...Object.keys(sitesKeyed1).concat(Object.keys(sitesKeyed2))]).values()) const result = uniqueSiteIds.map(siteId => ({ siteId, siteS1: sitesKeyed1[siteId], siteS2: sitesKeyed2[siteId], form: dataKeyed[siteId] || [], })); console.log(result); // as an object const result2 = uniqueSiteIds.reduce((acc, siteId) => { acc[siteId] = { siteS1: sitesKeyed1[siteId], siteS2: sitesKeyed2[siteId], form: dataKeyed[siteId] || [], }; return acc; }, {}); console.log(result2);
這可能不是最好的解決方案,但這是我想到的第一件事
[...new Set([...siteS1, ...siteS2, ...forms].map(s => s.siteid))].map(id => ({
siteS1: siteS1.find(s => s.siteid === id);
siteS2: siteS2.find(s => s.siteid === id);
form: form.filter(f => f.siteid === id);
}));
要合並兩個數組,通常需要先對它們進行排序。 排序后,標准算法為您提供 O(n+m) 復雜度。
只需查看https://www.geeksforgeeks.org/merge-two-sorted-arrays/他們已經很好地解釋了它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.