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

如何根据数组值获取对象键?含嵌套对象场景解决方案

问题描述

我编写了如下JavaScript代码,尝试通过getObjKey函数根据值获取对象的键:

function getObjKey(obj, value) {
  return Object.keys(obj).find(key => obj[key] === value);
}

const obj = {city1: ['Santiago','Germany'], city2: 'Chicago'};

console.log(getObjKey(obj, ['Santiago','Germany']));

希望获取数组['Santiago','Germany']对应的键city1,但执行上述代码无法实现;而传入字符串值'Chicago'时,能正常返回对应键city2。

后续对象结构更新为嵌套形式:

const obj = {
  city1: ['Santiago','Germany'], 
  city2: 'Chicago', 
  level1: {level2 : [{level3:'chennai'},{level4:'madurai'}]}
};

当传入数组[{level3:'chennai'},{level4:'madurai'}]作为参数时,也无法获取其对应的键level2。请问该如何解决这两个问题?

解决方案

核心原因

JavaScript中,原始值(字符串、数字等)按值比较,而引用值(数组、对象)按内存引用地址比较。你传入的目标数组/对象,和对象中存储的对应值虽然内容一致,但属于不同的内存引用,因此===判断会返回false,导致无法匹配。


1. 平级对象的解决方案

需要自定义深度比较函数,判断两个值的内容是否完全一致,再修改查找函数使用该比较逻辑:

// 深度比较两个值的内容是否相等
function isDeepEqual(a, b) {
  // 原始值或同一引用直接返回true
  if (a === b) return true;
  
  // 一方为null/undefined直接返回false
  if (a == null || b == null) return false;
  
  // 类型不同返回false
  if (typeof a !== typeof b) return false;
  
  // 数组比较:长度一致且每个元素深度相等
  if (Array.isArray(a) && Array.isArray(b)) {
    if (a.length !== b.length) return false;
    return a.every((item, idx) => isDeepEqual(item, b[idx]));
  }
  
  // 对象比较:键数量一致且每个键值对深度相等
  if (typeof a === 'object' && typeof b === 'object') {
    const keysA = Object.keys(a);
    const keysB = Object.keys(b);
    if (keysA.length !== keysB.length) return false;
    return keysA.every(key => isDeepEqual(a[key], b[key]));
  }
  
  // 其他不匹配情况
  return false;
}

// 修改后的键查找函数
function getObjKey(obj, targetValue) {
  return Object.keys(obj).find(key => isDeepEqual(obj[key], targetValue));
}

// 测试
const flatObj = {city1: ['Santiago','Germany'], city2: 'Chicago'};
console.log(getObjKey(flatObj, ['Santiago','Germany'])); // 输出: city1
console.log(getObjKey(flatObj, 'Chicago')); // 输出: city2

2. 嵌套对象的解决方案

如果需要遍历多层嵌套的对象结构,需要在查找函数中加入递归逻辑,遍历所有层级的键值对:

// 递归遍历嵌套对象,根据值查找对应键
function getNestedObjKey(obj, targetValue) {
  for (const key in obj) {
    // 只遍历对象自身的属性,排除原型链属性
    if (!obj.hasOwnProperty(key)) continue;
    
    const currentValue = obj[key];
    // 当前值匹配则返回键
    if (isDeepEqual(currentValue, targetValue)) {
      return key;
    }
    
    // 如果当前值是对象/数组,递归进入下一层查找
    if ((typeof currentValue === 'object' && currentValue != null) || Array.isArray(currentValue)) {
      const nestedKey = getNestedObjKey(currentValue, targetValue);
      if (nestedKey) return nestedKey;
    }
  }
  // 未找到匹配值时返回null
  return null;
}

// 测试
const nestedObj = {
  city1: ['Santiago','Germany'], 
  city2: 'Chicago', 
  level1: {level2 : [{level3:'chennai'},{level4:'madurai'}]}
};
console.log(getNestedObjKey(nestedObj, [{level3:'chennai'},{level4:'madurai'}])); // 输出: level2

注意事项

  • 若对象中存在多个内容相同的目标值,函数会返回第一个匹配到的键。
  • 上述深度比较函数未处理循环引用(如对象引用自身),如果你的数据存在这种场景,需要额外添加循环引用检测逻辑。

内容的提问来源于stack exchange,提问作者Aakash Pawan G P S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:30:56