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

如何用Lodash搜索含动态键的深层嵌套JSON并返回根对象?

使用Lodash搜索嵌套JSON(含动态键)

嘿,我完全懂你现在的需求——要在嵌套的JSON数据里用Lodash做模糊搜索,还得处理那些动态变化的键,而且只要任意指定位置匹配上,就得返回对应的根对象。我来给你一步步拆解出可行的解决方案:

首先先明确我们要覆盖的三个匹配场景:

  • 根对象的name字段
  • activities.routines下的动态键名称(比如示例里的"Biking"、"Kayaking")
  • activities.routines.*.details(动态键对应的详情字段)

同时要考虑activities可能是空数组、routines可能是空对象的容错情况。

完整实现代码

function searchText(collection, searchTerm) {
  // 统一转小写,避免大小写敏感问题
  const lowerSearchTerm = searchTerm.toLowerCase();
  
  return _.filter(collection, (rootObj) => {
    // 1. 检查name字段是否匹配
    const nameMatches = _.includes(rootObj.name.toLowerCase(), lowerSearchTerm);
    
    // 2. 检查activities嵌套结构中的匹配项
    const activitiesMatches = _.some(rootObj.activities, (activity) => {
      // 先判断当前activity的routines是否有内容,避免空对象报错
      if (!_.isEmpty(activity.routines)) {
        // 检查动态键名称是否匹配
        const routineKeyMatches = _.some(_.keys(activity.routines), (key) => 
          _.includes(key.toLowerCase(), lowerSearchTerm)
        );
        
        // 检查所有routine的details字段是否匹配
        const routineDetailsMatches = _.some(activity.routines, (routine) => 
          _.includes(routine.details.toLowerCase(), lowerSearchTerm)
        );
        
        // 键名或details有一个匹配,就算当前activity符合条件
        return routineKeyMatches || routineDetailsMatches;
      }
      // 若routines为空,直接返回false
      return false;
    });
    
    // 只要name或activities中有任意一个匹配,就保留这个根对象
    return nameMatches || activitiesMatches;
  });
}

代码逻辑拆解

  1. 统一大小写处理:先把搜索词转成小写,后续所有匹配都用小写对比,彻底解决大小写敏感问题。
  2. 根对象name匹配:和你之前实现的逻辑一致,用_.includes判断是否包含搜索词。
  3. 嵌套结构匹配:
    • 用_.some遍历activities数组,只要数组里有一个activity符合条件,就判定该根对象有效(避免全量遍历提升效率)。
    • 对每个activity,先通过_.isEmpty判断routines是否有内容,跳过空对象的无效遍历。
    • 动态键匹配:用_.keys()提取routines的所有动态键,再用_.some检查是否有键名包含搜索词。
    • details字段匹配:直接用_.some遍历routines的所有值(即每个routine对象),检查details字段是否匹配。
  4. 最终判定:只要name或嵌套结构中有任意一个匹配,就将该根对象加入结果集。

使用示例

假设你的数据源是:

const data = [
  {
    "name": "Bob's concourse",
    "activities": [
      {
        "day": "Monday",
        "routines": {
          "Biking": {
            "details": "won 3 trophies",
            "type": "road"
          },
          "Kayaking": {
            "details": "participated in 3 races",
            "type": "rhythm"
          }
        }
      }
    ]
  },
  {
    "name": "Alice's gym",
    "activities": []
  }
];
  • 调用searchText(data, "races"):返回第一个根对象(Kayaking的details匹配)
  • 调用searchText(data, "biking"):返回第一个根对象(动态键名"Biking"匹配)
  • 调用searchText(data, "bob"):返回第一个根对象(name字段匹配)
  • 调用searchText(data, "swim"):返回空数组(无匹配项)

额外容错提示

如果routines可能是undefined(而非空对象),可以把判断条件改成:

if (_.has(activity, 'routines') && !_.isEmpty(activity.routines))

进一步提升代码的健壮性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:46:28