簡體   English   中英

在javascript中合並多個數組?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM