¥
立即购买

JavaScript数组映射函数生成器

7 浏览
1 试用
0 购买
Dec 8, 2025更新

本提示词专为JavaScript开发场景设计,能够根据用户提供的数组名称和具体需求,生成符合最佳实践的map函数代码。通过明确的角色设定和技术规范,确保输出的代码具备高可读性、准确性和实用性,同时提供必要的技术说明和使用建议,帮助开发者快速理解函数逻辑并应用于实际项目开发中。

  • 函数定义
/**
 * 将 users 数组映射为用于表格展示的行数据。
 * - id:转为字符串
 * - fullName:trim 后拼接并将每一部分首字母大写
 * - age:由 birthdate 计算(按UTC年/月/日对齐,避免时区误差)
 * - role:映射为中文标签(可自定义 roleMap)
 * - avatar:缺失或空白使用默认图片
 * - active:布尔值转中文“启用/停用”
 *
 * @param {Array<Object>} users - 原始用户数据数组
 * @param {Object} [options]
 * @param {Object<string,string>} [options.roleMap] - 角色英文代码到中文标签的映射
 * @param {string} [options.defaultAvatar] - 默认头像地址
 * @param {string} [options.roleUnknownLabel] - 未知角色的中文占位
 * @param {Date}   [options.now] - 计算年龄的基准时间(便于测试或回放)
 * @returns {Array<Object>} 转换后的表格行数据
 */
function transformUsersForTable(
  users,
  {
    roleMap = {
      admin: '管理员',
      user: '用户',
      editor: '编辑',
      viewer: '访客',
    },
    roleUnknownLabel = '未知',
    defaultAvatar = '/img/default.png',
    now = new Date(),
  } = {}
) {
  if (!Array.isArray(users)) {
    throw new TypeError('transformUsersForTable(users): users 必须为数组');
  }

  return users.map((u) => {
    const id = String(u?.id ?? '');

    const fullName = buildFullName(u?.firstName, u?.lastName);

    const age = computeAgeUTC(parseBirthdateToUTC(u?.birthdate), now);

    const role = roleMap?.[u?.role] ?? roleUnknownLabel;

    const avatar = normalizeAvatar(u?.avatar, defaultAvatar);

    const active = Boolean(u?.active) ? '启用' : '停用';

    return { id, fullName, age, role, avatar, active };
  });
}

/* ---------- 辅助函数 ---------- */

/**
 * 规范化头像:缺失、null、undefined、空字符串或全空白则使用默认。
 */
function normalizeAvatar(avatar, defaultAvatar) {
  if (typeof avatar !== 'string') return defaultAvatar;
  const trimmed = avatar.trim();
  return trimmed ? trimmed : defaultAvatar;
}

/**
 * 将 firstName/lastName 去空白后拼接,并将每一部分首字母大写。
 * 仅对拉丁字母进行大小写处理;非拉丁字符不受影响。
 */
function buildFullName(firstName, lastName) {
  const parts = [firstName, lastName]
    .map((v) => (typeof v === 'string' ? v.trim() : ''))
    .filter(Boolean)
    .map(capitalizeWord);

  return parts.join(' ');
}

/**
 * 首字母大写,其余小写(仅对英文字母有意义)。
 */
function capitalizeWord(s) {
  if (!s) return '';
  const head = s.charAt(0).toUpperCase();
  const tail = s.slice(1).toLowerCase();
  return head + tail;
}

/**
 * 将 birthdate 解析为对齐到 UTC 的日期对象(仅保留年/月/日,时间置零)。
 * 支持:
 * - 字符串:优先匹配 YYYY-MM-DD;否则退化到 new Date()
 * - Date 或毫秒时间戳
 * 解析失败返回 null。
 */
function parseBirthdateToUTC(input) {
  if (!input) return null;

  // Date 实例
  if (input instanceof Date && !Number.isNaN(input.valueOf())) {
    return new Date(Date.UTC(input.getUTCFullYear(), input.getUTCMonth(), input.getUTCDate()));
  }

  // 毫秒时间戳
  if (typeof input === 'number') {
    const d = new Date(input);
    if (!Number.isNaN(d.valueOf())) {
      return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
    }
    return null;
  }

  // 字符串解析
  if (typeof input === 'string') {
    const s = input.trim();
    // 优先解析 YYYY-MM-DD,避免本地时区偏移
    const m = s.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/);
    if (m) {
      const y = +m[1];
      const mo = +m[2] - 1;
      const d = +m[3];
      return new Date(Date.UTC(y, mo, d));
    }
    // 退化解析
    const d2 = new Date(s);
    if (!Number.isNaN(d2.valueOf())) {
      return new Date(Date.UTC(d2.getUTCFullYear(), d2.getUTCMonth(), d2.getUTCDate()));
    }
  }

  return null;
}

/**
 * 基于 UTC 年/月/日计算年龄,避免时区导致的生日偏移。
 * 若 birthUTC 为空或在未来,返回 null。
 */
function computeAgeUTC(birthUTC, nowLocal = new Date()) {
  if (!birthUTC) return null;

  // 将 now 对齐到 UTC 的 Y/M/D
  const nowUTC = new Date(
    Date.UTC(
      nowLocal.getUTCFullYear(),
      nowLocal.getUTCMonth(),
      nowLocal.getUTCDate()
    )
  );

  let age = nowUTC.getUTCFullYear() - birthUTC.getUTCFullYear();

  const nowMonth = nowUTC.getUTCMonth();
  const birthMonth = birthUTC.getUTCMonth();

  if (
    nowMonth < birthMonth ||
    (nowMonth === birthMonth && nowUTC.getUTCDate() < birthUTC.getUTCDate())
  ) {
    age -= 1;
  }

  return age >= 0 ? age : null;
}
  • 参数说明
  1. users
    • 类型:Array
    • 说明:原始用户对象数组,元素可包含 id, firstName, lastName, birthdate, role, avatar, active 等字段(未提供的字段将按规则回退处理)。
    • options
      • roleMap:Object<string, string>,角色英文代码到中文标签的映射。默认包含 admin/user/editor/viewer。
      • roleUnknownLabel:string,未匹配到的角色显示文本,默认“未知”。
      • defaultAvatar:string,默认头像地址,默认 '/img/default.png'。
      • now:Date,年龄计算的基准时间,默认当前时间(可用于测试固定输出)。
      • 使用示例
      const users = [
        {
          id: 1,
          firstName: ' alice ',
          lastName: 'smith',
          birthdate: '1990-04-01',
          role: 'admin',
          avatar: '',
          active: true,
        },
        {
          id: '2',
          firstName: 'BOB',
          lastName: 'lee',
          birthdate: '1985-12-31T05:00:00Z',
          role: 'user',
          avatar: '/img/bob.png',
          active: 0,
        },
        {
          id: 3,
          firstName: '陈',
          lastName: '伟',
          birthdate: '2000-02-29',
          role: 'unknownRole',
          avatar: null,
          active: 'yes',
        },
        {
          id: 4,
          firstName: '  ',
          lastName: 'doe  ',
          birthdate: null,
          role: 'editor',
          active: false,
        },
      ];
      
      const rows = transformUsersForTable(users, {
        now: new Date('2025-01-01T00:00:00Z'),
        roleMap: {
          admin: '管理员',
          user: '用户',
          editor: '编辑',
          viewer: '访客',
          unknownRole: '未知角色',
        },
        defaultAvatar: '/img/default.png',
        roleUnknownLabel: '未知',
      });
      
      console.log(rows);
      /*
      [
        {
          id: '1',
          fullName: 'Alice Smith',
          age: 34,
          role: '管理员',
          avatar: '/img/default.png',
          active: '启用'
        },
        {
          id: '2',
          fullName: 'Bob Lee',
          age: 39,
          role: '用户',
          avatar: '/img/bob.png',
          active: '停用'
        },
        {
          id: '3',
          fullName: '陈 伟',
          age: 24,
          role: '未知角色',
          avatar: '/img/default.png',
          active: '启用'
        },
        {
          id: '4',
          fullName: 'Doe',
          age: null,
          role: '编辑',
          avatar: '/img/default.png',
          active: '停用'
        }
      ]
      */
      
      • 技术要点
      • 单次遍历:使用 Array.prototype.map 一次性完成转换,时间复杂度 O(n)。
      • 不可变转换:不修改原始 users 中的对象,返回全新数组。
      • 文本规范化:对 firstName/lastName 执行 trim 和首字母大写;仅对拉丁字母进行大小写处理,非拉丁文字不受影响。
      • 头像回退:对 undefined/null/空字符串/全空白统一回退到默认头像。
      • 布尔映射:active 通过 Boolean() 规范化后映射为“启用/停用”。
      • 角色映射:通过 roleMap 可扩展映射表;未知角色使用 roleUnknownLabel。
      • 年龄计算的时区稳定性:将出生日期与当前日期对齐到 UTC 的年/月/日后计算,避免本地时区导致的生日偏移。
      • 可测试性:可通过 options.now 注入固定时间,得到稳定、可预测的年龄结果。

      函数定义

      'use strict';
      
      /**
       * 将 products 转为前端展示格式
       * - id 保留
       * - title 去首尾空格并合并连续空格
       * - price 从“分”转为“元”,保留 2 位小数(字符串)
       * - discountedPrice = price*(1-discountRate),四舍五入到 2 位(字符串)
       * - inStock 布尔转“有货/缺货”
       * - releaseAt 格式化为 'YYYY-MM-DD'(UTC)
       * - tags 全部转小写、去空白并过滤空项
       * @param {Array<object>} products
       * @returns {Array<object>}
       */
      function mapProducts(products) {
        if (!Array.isArray(products)) return [];
      
        const clamp01 = (v) => {
          const n = Number(v);
          return Number.isFinite(n) ? Math.min(Math.max(n, 0), 1) : 0;
        };
      
        const normalizeTitle = (t) => String(t ?? '').trim().replace(/\s+/g, ' ');
      
        const toYuanString = (fen) => {
          const n = Number(fen);
          if (!Number.isFinite(n)) return '0.00';
          return (n / 100).toFixed(2);
        };
      
        // 将数字四舍五入到 2 位小数并以字符串返回
        const roundTo2String = (num) => {
          const n = Number(num);
          if (!Number.isFinite(n)) return '0.00';
          // 尽量避免浮点误差
          const i = Math.round(n * 100 + Number.EPSILON);
          return (i / 100).toFixed(2);
        };
      
        // 使用 UTC 保持跨时区一致的 YYYY-MM-DD
        const formatUTCDate = (value) => {
          const d = new Date(value);
          return Number.isNaN(d.getTime()) ? '' : d.toISOString().slice(0, 10);
        };
      
        const normalizeTags = (tags) =>
          Array.isArray(tags)
            ? tags
                .map((t) => String(t ?? '').trim().toLowerCase())
                .filter(Boolean)
            : [];
      
        return products.map((p) => {
          const priceYuanNumber = Number.isFinite(Number(p?.price)) ? Number(p.price) / 100 : 0;
          const discountRate = clamp01(p?.discountRate);
          const discounted = priceYuanNumber * (1 - discountRate);
      
          return {
            id: p?.id,
            title: normalizeTitle(p?.title),
            price: toYuanString(p?.price),                     // '999.00'
            discountedPrice: roundTo2String(discounted),       // '799.20'
            inStock: Boolean(p?.inStock) ? '有货' : '缺货',
            releaseAt: formatUTCDate(p?.releaseAt),            // 'YYYY-MM-DD'
            tags: normalizeTags(p?.tags),
          };
        });
      }
      

      参数说明

      • products: 数组
        • id: 任意类型,原样保留
        • title: 字符串,输出时会去首尾空格并折叠连续空白为单个空格
        • price: 数字或数字字符串(单位“分”),会转为“元”字符串并保留两位小数
        • discountRate: 折扣率(0~1),超出范围会被夹紧到 [0, 1]
        • inStock: 布尔或可转为布尔的值,true -> “有货”,否则 “缺货”
        • releaseAt: 可被 Date 构造解析的时间(时间戳/ISO字符串等),按 UTC 输出 'YYYY-MM-DD';解析失败则返回空字符串
        • tags: 字符串数组,每项会 trim、转小写,并过滤空字符串

      返回值:新的数组,每个元素为展示所需的数据结构,原数组不被修改。

      使用示例

      const products = [
        {
          id: 1,
          title: '  Apple   iPhone  16  ',
          price: 99900, // 分
          discountRate: 0.2,
          inStock: true,
          releaseAt: '2025-01-15T08:00:00Z',
          tags: [' Phone ', 'iOS', '  ']
        },
        {
          id: 2,
          title: '\nSony   TV 4K  ',
          price: '259900',
          discountRate: 0,
          inStock: false,
          releaseAt: '2024-12-31T00:00:00Z',
          tags: ['  Home ', 'Av ']
        }
      ];
      
      const viewModels = mapProducts(products);
      console.log(viewModels);
      /*
      [
        {
          id: 1,
          title: 'Apple iPhone 16',
          price: '999.00',
          discountedPrice: '799.20',
          inStock: '有货',
          releaseAt: '2025-01-15',
          tags: ['phone', 'ios']
        },
        {
          id: 2,
          title: 'Sony TV 4K',
          price: '2599.00',
          discountedPrice: '2599.00',
          inStock: '缺货',
          releaseAt: '2024-12-31',
          tags: ['home', 'av']
        }
      ]
      */
      

      技术要点

      • 纯函数与不可变性:不修改输入数组或其元素,返回新数组,便于测试与复用。
      • 金额处理:
        • price 由分转元使用 toFixed(2) 输出字符串,确保展示两位小数。
        • discountedPrice 使用整数化四舍五入策略(Math.round(n*100 + EPSILON)/100),再 toFixed(2) 输出。
      • 折扣安全性:discountRate 通过 clamp 到 [0, 1],防止异常折扣导致负价或超折扣。
      • 日期格式:使用 UTC 的 toISOString().slice(0,10) 生成 'YYYY-MM-DD',避免跨时区显示不一致。如需本地日期,可改用 getFullYear()/getMonth()/getDate 组合。
      • 文本与标签清洗:title 折叠任意空白为单空格;tags 统一小写、去空白并过滤空项。
      • 健壮性:对不可解析的数值与日期提供安全回退(金额默认为 '0.00',日期为空字符串,tags 默认为空数组)。

      函数定义:

      /**
       * 将订单数组转换为导出行数据
       * - 保留 orderNo、customerName
       * - phone 脱敏为前三位 + **** + 后四位(尽力处理非常规号码)
       * - total = Σ(items.price * items.qty) + shippingFee(缺省按 0),保留 2 位小数
       * - status 映射为中文(可覆盖)
       * - address = province + city + district + detail(忽略缺失片段)
       * - createdAt 格式化为 'YYYY-MM-DD HH:mm'
       * - couponCode 缺失填 'N/A'
       *
       * @param {Array<Object>} ordersData - 原始订单数组
       * @param {Object} [options]
       * @param {Record<string,string>} [options.statusMap] - 自定义状态映射(键使用小写英文状态)
       * @returns {Array<Object>} 转换后的导出行
       */
      export function mapOrdersToRows(ordersData, options = {}) {
        const defaultStatusMap = {
          pending: '待支付',
          paid: '已支付',
          processing: '处理中',
          shipped: '已发货',
          delivered: '已完成',
          completed: '已完成',
          complete: '已完成',
          success: '已完成',
          cancelled: '已取消',
          canceled: '已取消',
          closed: '已关闭',
          refunded: '已退款',
          refund_pending: '退款中',
        };
        const statusMap = { ...defaultStatusMap, ...(options.statusMap || {}) };
      
        const toNumberOrZero = (v) => {
          const n = Number(v);
          return Number.isFinite(n) ? n : 0;
        };
      
        const formatDateTime = (input) => {
          const d = new Date(input);
          if (Number.isNaN(d.getTime())) return '';
          const y = d.getFullYear();
          const m = String(d.getMonth() + 1).padStart(2, '0');
          const dd = String(d.getDate()).padStart(2, '0');
          const hh = String(d.getHours()).padStart(2, '0');
          const mm = String(d.getMinutes()).padStart(2, '0');
          return `${y}-${m}-${dd} ${hh}:${mm}`;
        };
      
        const maskPhone = (phone) => {
          const s = String(phone ?? '');
          // 常见 11 位手机号:前三位 + **** + 后四位
          const m = s.match(/^(\d{3})\d{4}(\d{4})$/);
          if (m) return `${m[1]}****${m[2]}`;
          // 通用回退:提取数字后尝试前三位 + **** + 后四位
          const digits = s.replace(/\D/g, '');
          if (digits.length >= 7) {
            return `${digits.slice(0, 3)}****${digits.slice(-4)}`;
          }
          // 无法安全脱敏则原样返回
          return s;
        };
      
        const buildAddress = (order) => {
          const addr =
            order.address && typeof order.address === 'object'
              ? order.address
              : {
                  province: order.province,
                  city: order.city,
                  district: order.district,
                  detail: order.detail,
                };
          const parts = ['province', 'city', 'district', 'detail']
            .map((k) => addr?.[k])
            .filter(Boolean);
          return parts.join('');
        };
      
        const source = Array.isArray(ordersData) ? ordersData : [];
        return source.map((order) => {
          const items = Array.isArray(order.items) ? order.items : [];
          const itemsTotal = items.reduce((sum, it) => {
            const price = toNumberOrZero(it?.price);
            const qty = toNumberOrZero(it?.qty);
            return sum + price * qty;
          }, 0);
          const shippingFee = toNumberOrZero(order.shippingFee);
          const total = (itemsTotal + shippingFee).toFixed(2);
      
          const rawStatus = String(order.status ?? '').toLowerCase();
          const status = statusMap[rawStatus] ?? '未知';
      
          return {
            orderNo: String(order.orderNo ?? ''),
            customerName: String(order.customerName ?? ''),
            phone: maskPhone(order.phone),
            total, // 字符串,保留两位小数
            status,
            address: buildAddress(order),
            createdAt: formatDateTime(order.createdAt),
            couponCode: order.couponCode ? String(order.couponCode) : 'N/A',
          };
        });
      }
      

      参数说明:

      • ordersData:数组,元素为订单对象,建议包含以下字段:
        • orderNo:订单号
        • customerName:客户名
        • phone:手机号或联系电话
        • items:数组,每项包含 price(单价)、qty(数量)
        • shippingFee:运费(可缺省)
        • status:英文状态(如 pending、paid、shipped 等)
        • address 或省市区字段:address 对象或 { province, city, district, detail }
        • createdAt:可被 Date 识别的时间(时间戳或 ISO 字符串)
        • couponCode:优惠码(可缺省)
      • options.statusMap:可选,覆盖或补充默认的英文状态到中文的映射,键建议使用小写英文状态。

      使用示例:

      import { mapOrdersToRows } from './mapOrdersToRows.js';
      
      const ordersData = [
        {
          orderNo: 'A20250101',
          customerName: '张三',
          phone: '13812340123',
          items: [
            { price: 99.9, qty: 2 },
            { price: '10', qty: '3' },
          ],
          shippingFee: 12,
          status: 'paid',
          address: { province: '浙江省', city: '杭州市', district: '西湖区', detail: '文三路100号' },
          createdAt: '2025-01-01T08:15:27+08:00',
          couponCode: '',
        },
        {
          orderNo: 'B20250102',
          customerName: '李四',
          phone: '(010) 8888-6666',
          items: [{ price: 50, qty: 1 }],
          // shippingFee 缺省
          status: 'shipped',
          province: '北京市',
          city: '北京市',
          district: '朝阳区',
          detail: '酒仙桥路1号',
          createdAt: 1735715400000, // 时间戳
          // couponCode 缺省
        },
      ];
      
      const rows = mapOrdersToRows(ordersData);
      /*
      预期输出 rows:
      [
        {
          orderNo: 'A20250101',
          customerName: '张三',
          phone: '138****0123',
          total: '332.80', // (99.9*2 + 10*3) + 12
          status: '已支付',
          address: '浙江省杭州市西湖区文三路100号',
          createdAt: '2025-01-01 08:15',
          couponCode: 'N/A'
        },
        {
          orderNo: 'B20250102',
          customerName: '李四',
          phone: '010****6666', // 提取数字后脱敏
          total: '50.00', // 仅商品总价,运费缺省按 0
          status: '已发货',
          address: '北京市北京市朝阳区酒仙桥路1号',
          createdAt: '2024-12-31 23:30', // 取本地时区格式化
          couponCode: 'N/A'
        }
      ]
      */
      

      技术要点:

      • 数值安全处理:对 price、qty、shippingFee 使用 Number 转换并在非数值时按 0 处理,避免 NaN 传播。
      • 金额格式:统一使用 toFixed(2) 输出两位小数字符串,适合导出报表场景。
      • 手机脱敏:优先匹配标准 11 位手机号;对包含非数字字符的座机或格式化字符串,提取数字后进行前三位+****+后四位的脱敏,无法安全脱敏时原样返回。
      • 状态映射:内置常见英文状态到中文的字典;支持传入 options.statusMap 进行覆盖/补充,未匹配到时返回“未知”。
      • 地址拼接:既支持 address 对象,也支持分散的 province/city/district/detail 字段;忽略缺失片段后无分隔符直接拼接,满足中文地址常规展示。
      • 日期格式:使用原生 Date 解析并按本地时区输出 'YYYY-MM-DD HH:mm';若输入不可解析,返回空字符串以避免中断。
      • 兼容与健壮性:对缺省字段进行合理的缺省处理(如运费、优惠码、items 数组),确保 map 操作稳定、无副作用。

      示例详情

      解决的问题

      让开发者用最少的描述,快速生成专业、可读、可直接粘贴使用的 JavaScript 数组映射函数;覆盖数据清洗、列表展示、字段映射、批量转换等高频场景;统一团队代码风格,减少返工与潜在缺陷,加速评审与上线,最终提升交付效率并降低人力成本。即刻试用:只需输入“数组名称 + 转换需求”,立刻得到可用代码、参数说明、示例与要点。

      适用用户

      前端开发工程师

      快速生成数组映射逻辑用于列表渲染、表单数据清洗与接口数据格式整理;统一命名与注释,减少手写错误,加速提测与联调。

      全栈开发者

      在服务端或脚本任务中批量转换数据;用内置示例快速接入现有模块,保证可读性与性能,缩短上线周期。

      数据可视化工程师

      把原始数据映射为图表组件所需结构,自动补默认值与类型标准化,避免空值导致的出图异常。

      特征总结

      一键生成符合最佳实践的map函数,按需映射数组结构,立即用于列表渲染与数据清洗。
      自动识别你的数组名称与转换目标,给出清晰命名与参数设计,避免后期维护混乱。
      内置注释与使用示例,同步输出调用方式和预期结果,降低沟通成本与上手难度。
      智能优化映射逻辑,避免深层嵌套与冗余代码,让代码更短、更稳、更易读。
      贴合前端常见场景,轻松处理接口数据格式化、字段重命名、默认值补齐与类型转换。
      提供技术要点与注意事项,提示性能与安全风险,让你的转换在复杂数据下仍稳定。
      支持模板化复用和轻量定制,保存常用映射模式,团队协作时一键复刻标准。
      生成前自动自查逻辑完整性,确保可直接运行,减少调试时间与线上回滚风险。
      输出结构统一、层次清晰,便于加入项目文档与代码评审,提升团队代码一致性。
      可作为学习教练,结合注释讲解函数思路,帮助新人快速掌握数组转换方法。

      如何使用购买的提示词模板

      1. 直接在外部 Chat 应用中使用

      将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。

      2. 发布为 API 接口调用

      把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。

      3. 在 MCP Client 中配置使用

      在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。

      AI 提示词价格
      ¥20.00元
      先用后买,用好了再付款,超安全!

      您购买后可以获得什么

      获得完整提示词模板
      - 共 444 tokens
      - 2 个可调节参数
      { 数组名称 } { 转换需求 }
      获得社区贡献内容的使用权
      - 精选社区优质案例,助您快速上手提示词
      使用提示词兑换券,低至 ¥ 9.9
      了解兑换券 →
      限时半价

      不要错过!

      半价获取高级提示词-优惠即将到期

      17
      :
      23
      小时
      :
      59
      分钟
      :
      59