js与数组,对象,树相关的手撕

21 阅读2分钟

js与数组,对象,树相关的手撕

数组扁平化

[1, 2, [3, 4, [5, 6]]]  => [1, 2, 3, 4, 5, 6]
function flat(arr, d = Infinity) {
  return d > 0
    ? arr.reduce(
        (acc, val) => acc.concat(Array.isArray(val) ? flat(val, d - 1) : val),
        []
      )
    : arr;
}
function flat(arr) {
  return arr
    .toString()
    .split(",")
    .map((item) => Number(item));
}
function flat(arr) {
  while (arr.some((item) => Array.isArray(item))) {
    arr = [].concat(...arr);
  }
  return arr;
}

输出嵌套数组层数

const nestedArray = [1, [2, [3, [4]]], 5];
const depth = getArrayDepth(nestedArray);
console.log(`嵌套数组的层数为: ${depth}`); // 输出: 嵌套数组的层数为: 4
function getArrayDepth(arr) {
  let depth = 0;
  if (Array.isArray(arr)) {
    arr.forEach((item) => {
      depth = Math.max(depth, getArrayDepth(item));
    });
    return depth + 1;
  } else {
    return 0;
  }
}

对象扁平化

{
  a: {
    b: {
      c: {
        dd: "abcdd",
      },
    },
    d: {
      xx: "adxx",
    },
    e: "ae",
  },
} 

=>

{
  "a.b.c.dd": "abcdd",
  "a.d.xx": "adxx",
  "a.e": "ae",
}
function flat(obj, prefix = "", result = {}) {
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      const newKey = prefix ? prefix + "." + key : key;

      if (typeof obj[key] === "object" && obj[key] !== null) {
        // 如果值是对象,则递归处理
        flat(obj[key], newKey, result);
      } else {
        // 如果值不是对象,则直接添加到结果对象
        result[newKey] = obj[key];
      }
    }
  }
  return result;
}

数组对象转树

[
  { id: 1, parent_id: 0, name: "北京市" },
  { id: 2, parent_id: 0, name: "上海市" },
  { id: 11, parent_id: 1, name: "顺义区" },
  { id: 12, parent_id: 1, name: "朝阳区" },
  { id: 21, parent_id: 2, name: "静安区" },
  { id: 22, parent_id: 2, name: "黄浦区" },
]

=>

[
  {
    "id": 1,
    "parent_id": 0,
    "name": "北京市",
    "children": [
      {
        "id": 11,
        "parent_id": 1,
        "name": "顺义区"
      },
      {
        "id": 12,
        "parent_id": 1,
        "name": "朝阳区"
      }
    ]
  },
  {
    "id": 2,
    "parent_id": 0,
    "name": "上海市",
    "children": [
      {
        "id": 21,
        "parent_id": 2,
        "name": "静安区"
      },
      {
        "id": 22,
        "parent_id": 2,
        "name": "黄浦区"
      }
    ]
  }
]
function arrayToTree(list, root) {
  const children = list
    .filter((item) => item.parent_id === root)
    .map((item) => {
      const childrenNodes = arrayToTree(list, item.id);
      // 只有当有子节点时才添加children属性
      return childrenNodes.length > 0
        ? { ...item, children: childrenNodes }
        : { ...item };
    });
  return children;
}

在树结构中查找从根节点到目标节点的路径

const tree = {
  id: 1,
  children: [
    {
      id: 2,
      children: [{ id: 4, children: [] }],
    },
    {
      id: 3,
      children: null,
    },
  ],
};

console.log(findPath(tree, 4)); // 输出 [1, 2, 4]
console.log(findPath(tree, 3)); // 输出 [1, 3]
console.log(findPath(tree, 5)); // 输出 []
function findPath(tree, targetId) {
  if (!tree) return [];

  if (tree.id === targetId) return [tree.id];

  if (!tree.children) return [];

  for (const child of tree.children) {
    const path = findPath(child, targetId);
    if (path.length) return [tree.id, ...path];
  }

  return [];
}