2026-01-19 10:21:18 +08:00

178 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 数组与字符串操作
## 1. 数组去重(多种方法)
> **场景**:标签列表去重、下拉选项去重、用户列表按 ID 去重、搜索历史去重。
> **解决**:数据列表中存在重复项影响展示或数据处理的问题。
```js
// 方法1: Set 自动去重,最简洁
const unique1 = arr => [...new Set(arr)];
// 方法2: filter + indexOf只保留第一次出现的元素
const unique2 = arr => arr.filter((v, i) => arr.indexOf(v) === i);
// 方法3: reduce 累加,不存在才添加
const unique3 = arr => arr.reduce((acc, v) => acc.includes(v) ? acc : [...acc, v], []);
// 方法4: 对象数组按属性去重
const uniqueByKey = (arr, key) => {
const map = new Map(); // 用 Map 存储已出现的 key
arr.forEach(item => !map.has(item[key]) && map.set(item[key], item));
return [...map.values()]; // 返回去重后的值
};
```
## 2. 扁平化数组
> **场景**:多级分类菜单拍平为一维数组、树形结构转平铺列表、处理嵌套 JSON 数据。
> **解决**:嵌套数组不便于遍历、查找和渲染的问题。
```js
// 递归实现:支持指定展开深度
function flatten(arr, depth = Infinity) {
return arr.reduce((acc, val) => {
// 如果是数组且深度>0递归展开
return acc.concat(
Array.isArray(val) && depth > 0 ? flatten(val, depth - 1) : val
);
}, []);
}
// 迭代实现(使用栈):避免递归栈溢出
function flattenIterative(arr) {
const stack = [...arr]; // 复制数组作为栈
const result = [];
while (stack.length) {
const item = stack.pop(); // 从栈顶取出
// 是数组则展开压回栈,否则加入结果
Array.isArray(item) ? stack.push(...item) : result.unshift(item);
}
return result;
}
// 原生方法ES2019+
arr.flat(Infinity); // Infinity 表示完全展开
```
## 3. 字符串反转
> **场景**:回文判断预处理、文本效果处理、简单加密/混淆。
> **解决**JS 没有内置字符串反转方法,需要手工实现。
```js
// 方法1拆分成数组 -> 反转 -> 拼接
const reverse = str => str.split('').reverse().join('');
// 方法2使用扩展运算符支持 Unicode 字符)
const reverse2 = str => [...str].reverse().join('');
```
## 4. 判断回文
> **场景**:车牌号校验、特殊编码检测、文字游戏、算法题基础。
> **解决**:判断字符串正反读是否一致,常作为算法题输入校验或中间步骤。
```js
// 方法1清理后比较反转结果
const isPalindrome = str => {
// 转小写并去除非字母数字字符
const clean = str.toLowerCase().replace(/[^a-z0-9]/g, '');
return clean === clean.split('').reverse().join('');
};
// 方法2双指针法性能更优
const isPalindrome2 = str => {
const s = str.toLowerCase().replace(/[^a-z0-9]/g, '');
let left = 0, right = s.length - 1;
while (left < right) {
// 从两端向中间比较
if (s[left++] !== s[right--]) return false;
}
return true;
};
```
## 5. 最长公共前缀
> **场景**:搜索联想提取、路径匹配、文件名批量处理、自动补全功能。
> **解决**:批量字符串中提取共同前缀以进行分类或缩短展示。
```js
function longestCommonPrefix(strs) {
if (!strs.length) return '';
let prefix = strs[0]; // 以第一个字符串为初始前缀
for (let i = 1; i < strs.length; i++) {
// 逐步缩短前缀,直到它是当前字符串的前缀
while (strs[i].indexOf(prefix) !== 0) {
prefix = prefix.slice(0, -1); // 去掉最后一个字符
if (!prefix) return ''; // 前缀为空,无公共前缀
}
}
return prefix;
}
// 示例: ["flower","flow","flight"] => "fl"
```
## 6. 模板字符串解析
> **场景**:简易模板引擎、邮件/短信模板填充、国际化 i18n 文本替换。
> **解决**:将模板字符串中的占位符替换为实际数据,类似 Mustache/Handlebars 语法。
```js
// 基础版:支持 {{key}} 语法
function render(template, data) {
// \{\{(\w+)\}\} 匹配 {{xxx}}\w+ 捕获 key
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
return data[key] !== undefined ? data[key] : match; // 无值则保留原样
});
}
// 进阶版:支持嵌套属性 {{a.b.c}}
function renderDeep(template, data) {
return template.replace(/\{\{(.+?)\}\}/g, (match, path) => {
const keys = path.trim().split('.'); // 按 . 拆分路径
let value = data;
for (const key of keys) {
value = value?.[key]; // 逐层取值,可选链防止报错
if (value === undefined) return match;
}
return value;
});
}
// 使用示例
render('Hello, {{name}}!', { name: 'World' }); // "Hello, World!"
renderDeep('{{user.info.name}}', { user: { info: { name: 'Tom' } } }); // "Tom"
```
## 7. 数组按属性去重并排序
> **场景**:用户列表按 ID 去重后按注册时间排序、商品列表按 SKU 去重后按价格排序。
> **解决**:对象数组的去重和排序组合操作,常见业务需求。
```js
function uniqueAndSort(arr, key, sortKey, order = 'asc') {
// 第一步:按指定 key 去重
const map = new Map();
arr.forEach(item => !map.has(item[key]) && map.set(item[key], item));
// 第二步:按指定 sortKey 排序
return [...map.values()].sort((a, b) => {
return order === 'asc'
? a[sortKey] - b[sortKey] // 升序
: b[sortKey] - a[sortKey]; // 降序
});
}
// 示例
const users = [
{ id: 1, name: 'Tom', age: 20 },
{ id: 2, name: 'Jerry', age: 18 },
{ id: 1, name: 'Tom2', age: 25 } // id 重复,会被过滤
];
uniqueAndSort(users, 'id', 'age'); // 按 id 去重,按 age 升序排序
```