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

如何简化从List<Info>提取非空UserId至string[]的LINQ代码?

更简洁高效的实现方案

当然有更优雅高效的写法啦!你的原代码需要两次遍历List<Info>集合,还得处理两个中间数组再合并,我们可以通过一次遍历完成所有操作,同时简化空值处理逻辑。

优化后的简洁实现

var userIds = Info
    .SelectMany(info => 
        // 合并当前Info中Rhistory和Vhistory的有效UserId序列
        (info.Rhistory?.Select(rh => rh.User?.UserId) ?? Enumerable.Empty<string>())
        .Concat(info.Vhistory?.Select(vh => vh.User?.UserId) ?? Enumerable.Empty<string>())
    )
    .Where(id => !string.IsNullOrEmpty(id)) // 过滤空/空白ID
    .Distinct() // 去重
    .ToArray();

代码解释

  1. 一次遍历集合:用SelectMany直接遍历每个Info对象,同时展开它的Rhistory和Vhistory中的UserId,避免多次遍历原集合,提升性能(尤其是集合规模较大时)。
  2. 安全的空值处理:
    • 使用?.空条件运算符,避免Rhistory/Vhistory/User为null时引发空引用异常。
    • 用?? Enumerable.Empty<string>()确保当历史列表为null时返回空序列,不会中断链式调用。
  3. 合并与过滤:通过Concat合并两个历史列表的UserId序列,然后统一过滤空值、去重,最后转成数组。

进一步优化(可复用性)

如果后续还有类似的XXXhistory类需要提取UserId,可以把提取逻辑抽成复用方法,让代码更清晰:

// 通用的UserId提取方法
IEnumerable<string> ExtractUserIds<T>(IEnumerable<T> historyList) where T : class
{
    return historyList?.Select(item => item.User?.UserId) ?? Enumerable.Empty<string>();
}

// 调用方式
var userIds = Info
    .SelectMany(info => ExtractUserIds(info.Rhistory).Concat(ExtractUserIds(info.Vhistory)))
    .Where(id => !string.IsNullOrEmpty(id))
    .Distinct()
    .ToArray();

这样不仅代码更整洁,后续新增类似的历史类型时,直接复用ExtractUserIds方法即可,扩展性更强。

内容的提问来源于stack exchange,提问作者Divya Agrawal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 22:03:11