簡體   English   中英

根據另一個數組和條件過濾一組對象

[英]Filter an array of objects based on another array and a condition

我正在努力根據特定條件從一組對象中檢索一個子集。 我有以下格式的對象數組:

const messages = [
    {
        summary: '[x1fg66pwq-qft] Second reminder to submit supporting documents',
        date: '1624652200',
        type: 1
    },
    {
        summary: '[x1fg66pwq-fgh] Final reminder to submit supporting documents',
        date: '1629058600',
        type: 4
    },
    {
        summary: '[zy9l89ptb-yuw] Please submit your proof of address',
        date: '1631708200',
        type: 2
    },
    {
        summary: '[ggk9nygh8-pmn] Your application has been successful.',
        date: '1634300200',
        type: 1
    },
]

還有另一個數組根據摘要方括號中的消息 ID 提供要檢索的消息:

const messageIds = ['x1fg66pwq', 'zy9l89ptb'];

結果應該是根據messageIds數組中的內容檢索最新消息。 日期字段以紀元為單位。

const result = [
    {
        summary: '[x1fg66pwq] Final reminder to submit supporting documents',
        date: '1629058600',
        type: 4
    },
    {
        summary: '[zy9l89ptb] Please submit your proof of address',
        date: '1631708200',
        type: 2
    },
]

為了實現上述目的,我嘗試組合一個過濾器並找到對我不起作用的:

const result = messages.filter((message) =>
        messageIds.find(id => message.summary.includes(testEvent))
    );

我希望上面返回數組中指定摘要的第一個結果。 但是,這總是為我返回完整的數組而不過濾。 有人可以幫我實現這一目標嗎?

如果我正確理解您的問題,我認為您只需要在最后進行sort

.sort((b,a) => +a.date - +b.date)

 const messages = [{ summary: '[x1fg66pwq-qft] Second reminder to submit supporting documents', date: '1624652200', type: 1 }, { summary: '[x1fg66pwq-fgh] Final reminder to submit supporting documents', date: '1629058600', type: 4 }, { summary: '[zy9l89ptb-yuw] Please submit your proof of address', date: '1631708200', type: 2 }, { summary: '[ggk9nygh8-pmn] Your application has been successful.', date: '1634300200', type: 1 }, ] const messageIds = ['x1fg66pwq', 'zy9l89ptb']; const result = messages.filter((message) => messageIds.some(id => message.summary.includes(id)) ).sort((b, a) => +a.date - +b.date); console.log(result)

當您查找最新消息時,您可以首先創建一個 map 或普通 object,以目標消息 ID 為鍵,然后為每個消息分配具有最大date屬性值的消息:

 const messages = [{summary: '[x1fg66pwq-qft] Second reminder to submit supporting documents',date: '1624652200',type: 1},{ summary: '[x1fg66pwq-fgh] Final reminder to submit supporting documents',date: '1629058600', type: 4},{ summary: '[zy9l89ptb-yuw] Please submit your proof of address',date: '1631708200',type: 2},{ summary: '[ggk9nygh8-pmn] Your application has been successful.', date: '1634300200',type: 1},]; const messageIds = ['x1fg66pwq', 'zy9l89ptb']; // Create object keyed by the message ids: let obj = Object.fromEntries(messageIds.map(id => [id, null])); // Link the message to each id with minimal date for (let msg of messages) { let id = msg.summary.match(/^\[(.*?)-/)?.[1]; if (obj[id] === null || +msg.date > +obj[id]?.date) obj[id] = msg; } let result = Object.values(obj); console.log(result);

這很容易。 只需將它們串在一起即可:

 const matches = (messages, ids) => ids.flatMap ( id => messages.filter (({summary}) => summary.startsWith ('[' + id)).sort (({date: a}, {date: b}) => b - a).slice (0, 1) ) const messages = [{summary: '[x1fg66pwq-qft] Second reminder to submit supporting documents', date: '1624652200', type: 1}, {summary: '[x1fg66pwq-fgh] Final reminder to submit supporting documents', date: '1629058600', type: 4}, {summary: '[zy9l89ptb-yuw] Please submit your proof of address', date: '1631708200', type: 2}, {summary: '[ggk9nygh8-pmn] Your application has been successful.', date: '1634300200', type: 1}] const messageIds = ['x1fg66pwq', 'zy9l89ptb'] console.log (matches (messages, messageIds))

此版本將簡單地忽略不匹配的 id。 這可能是也可能不是你想要的。 如果您必須為每個 id 搜索大量數據,它也會做一些愚蠢的事情:它通過對它們進行排序並選擇第一個來找到最大值。 對於小數據,這很好。 對於較大的數據(可能首先出現問題的可能是數十萬或數百萬),這是O (n log (n)) ,它比以下技術慢,即O (n)

 const maxBy = (fn) => (xs) => xs.reduce ( ({curr, max}, x) => fn(x) > max? {curr: x, max: fn (x)}: {curr, max}, {curr: null, max: -Infinity} ).curr const matches = (messages, ids) => ids.flatMap ( id => maxBy (({date}) => Number(date)) (messages.filter (({summary}) => summary.startsWith ('[' + id))) ) const messages = [{summary: '[x1fg66pwq-qft] Second reminder to submit supporting documents', date: '1624652200', type: 1}, {summary: '[x1fg66pwq-fgh] Final reminder to submit supporting documents', date: '1629058600', type: 4}, {summary: '[zy9l89ptb-yuw] Please submit your proof of address', date: '1631708200', type: 2}, {summary: '[ggk9nygh8-pmn] Your application has been successful.', date: '1634300200', type: 1}] const messageIds = ['x1fg66pwq', 'zy9l89ptb'] console.log (matches (messages, messageIds))

這使用maxBy function 遍歷列表以根據提供的 function 找到最大值,返回null為空數組。

在沒有找到 id 的情況下,此版本將在 output 中包含null 這可能是首選行為,但如果不是,您可以包裝它以過濾 output 以獲得非空值。

顯然,在這些解決方案中的任何一個中,您都可以將summary.startsWith ('[' + id)替換為summary.includes (id) ,這更靈活,但可能不太精確。

const result = messages.filter(function(e) {
    return messageIds.find(id => e.summary.includes(id))
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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