You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按ID匹配过滤两个结构体数组并关联指定属性信息?

按ID匹配关联用户与文章数组的最优实现方式

需求背景

现有两个结构体定义:

struct User {
    let id: Int
    let name: String
    var arts: [Article]?
}

struct Article {
    let userId: Int
    let id: Int
    let title: String
    let body: String
}

需将[User]数组与[Article]数组按User.id == Article.userId的规则关联,把每个用户对应的所有文章赋值到其arts属性中。

原始实现及问题

用户最初的实现代码:

var articles = [Article]()
var users = [User]()

self?.articles.forEach({ article in
    guard let userIndex = self?.users.firstIndex(where: { $0.id == article.userId }) else {
        print("Failed to find a User by UserID")
        return
    }
    self?.users[userIndex].arts?.append(article)
})

该实现的核心问题是时间复杂度高:每遍历一篇文章都要遍历整个用户数组查找匹配项,整体复杂度为O(n*m),当数据量较大时性能会明显下降;同时可选值的append操作存在空值风险,代码可读性也较差。

最优实现方案

通过字典分组预处理文章数组,将查找操作的时间复杂度降为O(1),整体复杂度优化为O(n + m),代码更简洁可靠。

方案1:生成新的用户数组(推荐,避免原数组修改副作用)

// 1. 按userId将文章分组,构建映射字典
let articlesByUserId = Dictionary(grouping: articles, by: { $0.userId })

// 2. 遍历用户数组,匹配对应文章
let updatedUsers = users.map { user in
    var mutableUser = user
    // 直接赋值对应文章数组,无则赋值空数组
    mutableUser.arts = articlesByUserId[user.id] ?? []
    return mutableUser
}

方案2:直接修改原用户数组

如果需要直接修改原数组而非生成新数组,可使用索引遍历:

let articlesByUserId = Dictionary(grouping: articles, by: { $0.userId })

for index in users.indices {
    users[index].arts = articlesByUserId[users[index].id] ?? []
}

方案优势

  • 性能大幅提升:预分组仅需遍历一次文章数组,后续用户匹配为O(1)查找,数据量大时优势明显
  • 代码简洁安全:避免嵌套遍历和索引操作,同时处理了arts的空值情况,无需额外的可选值判断
  • 可读性更强:逻辑清晰,通过字典映射直接关联用户与文章,意图明确

内容的提问来源于stack exchange,提问作者Josué H.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 08:54:26