每日一道算法Day26

368 阅读1分钟

题目描述:

给定一个源对象和一个包含键值对的目标对象, 找到目标对象中的键与值在源对象中的键值路径.

举个栗子:

const obj = {
      a: { b: 1, c: 2 },
      d: {
        e: 3,
        f: {
          g: 4,
          h: 5,
          l: 7
        },
      },
      i: {
        j: 6,
        k: {
          l: 7,
          m: 8,
        },
      },
    };
    
    {value:7, key:'l'}  ===> [['d', 'f', 'l'], ['i', 'k', 'l']]
    {value:7, key:'m'}  ===> []
    {valueu:2, key:'c'} ===> [['a', 'c']]

大致思路:

遍历源对象键值, 若该键值对应的值为数值, 则比较该键值与目标键值是否相匹配, 匹配则将该键push进数组, 若为对象, 则进行递归操作。

代码如下:

function getObjPath(obj: { [key in string]: any }, keyValue: { key: string, value: number }): string[][] {
  /定义返回值
  const result: string[][] = [];
  
  //递归函数
  const fn = (o: { [key in string]: any }, count: number = 0) => {
    const res = Object.keys(o).reduce((acc, cur) => {
      const val = o[cur];
      if (typeof val !== 'number') {
      //当前值为一个对象, 进行递归操作
        const arr = fn(val, count + 1);
        //判断函数是否为null, 为null则说明没匹配上
        if (arr) {
          //匹配上了, 将当前键与返回值组合, 生成path
          acc = [cur, ...arr];
          //判断当前执行环境是否为最外层, 是则将path push进最后的返回值中
          count === 0 && result.push(acc);
        }
      } else if (keyValue.key === cur && keyValue.value === val) {
      //匹配上了,将键值push进数组
        acc.push(cur);
      }
      return acc;
    }, [] as string[]);

    return res.length ? res : null;
  };

  fn(obj);

  return result;
}