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

TypeScript 两次forEach循环实现逻辑的最优解决方案咨询

优化方案

原代码的核心问题是对list数组做了两次完整遍历,当数组规模较大时会产生不必要的性能开销,同时直接修改入参数组的内部元素可能产生预期外的副作用,且fileToReplace用了any类型存在类型安全隐患。

优化后代码

// 先定义明确的类型,替换any
interface ListItem {
  id: string;
  files: Array<{id: string; name: string}>;
}

const shift = (
  list: ListItem[],
  fileId: string,
  folderId: string
): ListItem[] => {
  if (!list.length) {
    throw new Error('This resource cannot be empty');
  }

  let fileToMove: ListItem['files'][number] | null = null;
  let targetFolder: ListItem | null = null;

  // 仅遍历一次list数组,同时查找目标文件和目标文件夹
  for (const item of list) {
    // 查找并移除目标文件
    const fileIndex = item.files.findIndex(file => file.id === fileId);
    if (fileIndex > -1 && !fileToMove) {
      fileToMove = item.files[fileIndex];
      item.files.splice(fileIndex, 1);
    }
    // 匹配目标文件夹
    if (item.id === folderId && !targetFolder) {
      targetFolder = item;
    }
    // 两个目标都找到后直接终止遍历,无需跑完整个数组
    if (fileToMove && targetFolder) break;
  }

  if (!fileToMove) {
    throw new Error('You cannot move a folder');
  }
  if (!targetFolder) {
    throw new Error('You cannot specify a file as the destination');
  }

  targetFolder.files.push(fileToMove);
  // 如果需要避免修改原数组,可返回浅拷贝版本 [...list],根据业务需求选择
  return list;
};

核心优化点

  • 遍历次数从2次压缩到1次,且找到目标元素后直接终止遍历,数组规模越大性能提升越明显
  • 替换掉不安全的any类型,用明确的类型定义保证类型安全
  • 用findIndex代替嵌套forEach循环,逻辑更清晰,也规避了forEach无法提前终止的缺陷
  • 变量命名更语义化,将fileToReplace改为fileToMove更贴合移动文件的业务逻辑

如果你的场景需要immutable数据流、不能修改原入参数组,可以用以下无副作用的版本:

const shiftImmutable = (
  list: ListItem[],
  fileId: string,
  folderId: string
): ListItem[] => {
  if (!list.length) {
    throw new Error('This resource cannot be empty');
  }

  let fileToMove: ListItem['files'][number] | null = null;
  return list.map(item => {
    // 浅拷贝当前项,不修改原数据
    const newItem = {...item, files: [...item.files]};
    // 处理文件移除逻辑
    if (!fileToMove) {
      const fileIndex = newItem.files.findIndex(f => f.id === fileId);
      if (fileIndex > -1) {
        fileToMove = newItem.files[fileIndex];
        newItem.files.splice(fileIndex, 1);
      }
    }
    // 处理文件移入逻辑
    if (newItem.id === folderId && fileToMove) {
      newItem.files.push(fileToMove);
    }
    return newItem;
  });
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 20:39:03