文章列表

数组操作大全

Champ2025.12.18 16:07访问量0 次阅读
数组操作大全
Js中的数组操作方法大全

一、创建数组

// 字面量创建
const arr1: number[] = [1, 2, 3];
const arr2: Array<string> = ["a", "b", "c"]; // 泛型语法

// 构造函数创建
const arr3: number[] = new Array(1, 2, 3);
const emptyArr: number[] = new Array(3); // 长度为3的空数组

// 使用 Array.from()
const arr4: number[] = Array.from([1, 2, 3]);
const arr5: number[] = Array.from({ length: 5 }, (_, i) => i * 2); // [0, 2, 4, 6, 8]

// 使用 Array.of()
const arr6: number[] = Array.of(1, 2, 3, 4, 5);

二、增删改查基础操作

1. 添加元素

const fruits: string[] = ["apple", "banana"];

// 末尾添加
fruits.push("orange"); // ["apple", "banana", "orange"]
const newLength = fruits.push("grape", "mango"); // 返回新长度

// 开头添加
fruits.unshift("strawberry"); // ["strawberry", "apple", "banana", ...]

// 任意位置添加 (使用 splice)
//array.splice(startIndex(负数表示从后往前,超出长度从末尾开始), deleteCount(超出长度删除所有), item1, item2, ..., itemN)  返回被删除元素组成的数组
fruits.splice(2, 0, "peach"); // 在索引2处插入,不删除元素
// ["strawberry", "apple", "peach", "banana", ...]

2. 删除元素

const numbers: number[] = [1, 2, 3, 4, 5];

// 删除最后一个
const last = numbers.pop(); // last = 5, numbers = [1, 2, 3, 4]

// 删除第一个
const first = numbers.shift(); // first = 1, numbers = [2, 3, 4]

// 删除指定位置 (splice)
const removed = numbers.splice(1, 2); // 从索引1开始删除2个元素
// removed = [3, 4], numbers = [2]

// 删除所有元素
numbers.length = 0; // []

3. 修改元素

const colors: string[] = ["red", "green", "blue"];

// 直接赋值
colors[1] = "yellow"; // ["red", "yellow", "blue"]

// 使用 splice 替换
colors.splice(0, 1, "purple"); // 替换索引0的元素
// ["purple", "yellow", "blue"]

// 使用 fill 填充
const filled = new Array(3).fill(0); // [0, 0, 0]
filled.fill(1, 1, 3); // [0, 1, 1] (从索引1开始到3填充1)

4. 查找元素

const users = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" },
  { id: 3, name: "Alice" }
];

// 根据值查找索引
const index = users.findIndex(user => user.name === "Bob"); // 1

// 查找元素
const user = users.find(user => user.id === 2); // { id: 2, name: "Bob" }

// 检查是否存在
const hasAlice = users.some(user => user.name === "Alice"); // true

// 检查是否全部满足
const allHaveId = users.every(user => user.id > 0); // true

// 线性查找
const indexOfAlice = users.indexOf(users.find(u => u.name === "Alice")!); // 0
const lastIndexOfAlice = users.lastIndexOf(users.find(u => u.name === "Alice")!); // 2

三、遍历方法

const numbers: number[] = [1, 2, 3, 4, 5];

// forEach - 单纯遍历
numbers.forEach((num, index) => {
  console.log(`Index ${index}: ${num}`);
});

// map - 返回新数组
const doubled = numbers.map(num => num * 2); // [2, 4, 6, 8, 10]

// filter - 过滤
const even = numbers.filter(num => num % 2 === 0); // [2, 4]

// reduce - 累加
const sum = numbers.reduce((acc, curr) => acc + curr, 0); // 15
const max = numbers.reduce((a, b) => Math.max(a, b)); // 5

// reduceRight - 从右向左累加
const reversedStr = ["a", "b", "c"].reduceRight((acc, curr) => acc + curr); // "cba"

// flatMap - 先map后flat(一层)
const nested = [1, 2, 3].flatMap(x => [x, x * 2]); // [1, 2, 2, 4, 3, 6]

四、数组转换

// slice - 创建子数组(浅拷贝)
const arr = [1, 2, 3, 4, 5];
const slice1 = arr.slice(1, 3); // [2, 3] (索引1到3,不包含3)
const slice2 = arr.slice(-2); // [4, 5] (最后两个)

// concat - 合并数组
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = arr1.concat(arr2, [5, 6]); // [1, 2, 3, 4, 5, 6]

// flat - 扁平化数组
const nestedArr = [1, [2, 3], [4, [5, 6]]];
const flat1 = nestedArr.flat(); // [1, 2, 3, 4, [5, 6]]
const flat2 = nestedArr.flat(2); // [1, 2, 3, 4, 5, 6]

// join - 转为字符串
const str = arr.join(", "); // "1, 2, 3, 4, 5"

// toString / toLocaleString
const dateArr = [new Date(), new Date()];
dateArr.toString(); // "Thu Dec 12 2024..."
dateArr.toLocaleString('zh-CN'); // "2024/12/12..."

五、排序和反转

// sort - 排序(原地修改)
const unsorted = [3, 1, 4, 1, 5];
unsorted.sort(); // [1, 1, 3, 4, 5]

// 自定义排序
const users = [
  { name: "Alice", age: 25 },
  { name: "Bob", age: 30 },
  { name: "Charlie", age: 20 }
];

users.sort((a, b) => a.age - b.age); // 按年龄升序
users.sort((a, b) => b.age - a.age); // 按年龄降序
users.sort((a, b) => a.name.localeCompare(b.name)); // 按名字字母排序

// reverse - 反转(原地修改)
const arr = [1, 2, 3];
arr.reverse(); // [3, 2, 1]

// 创建排序后的新数组(不修改原数组)
const sorted = [...users].sort((a, b) => a.age - b.age);

六、查找和验证

const numbers = [1, 2, 3, 4, 5, NaN];

// includes - 检查包含(ES7)
const hasThree = numbers.includes(3); // true
const hasNaN = numbers.includes(NaN); // true (与 indexOf 不同)

// indexOf / lastIndexOf
const firstIndex = numbers.indexOf(3); // 2
const lastIndex = numbers.lastIndexOf(3); // 2

// find / findIndex / findLast / findLastIndex(ES2023)
const arr = [5, 12, 8, 130, 44];
const found = arr.find(element => element > 10); // 12
const foundIndex = arr.findIndex(element => element > 10); // 1
const foundLast = arr.findLast(element => element > 10); // 44 (ES2023)
const foundLastIndex = arr.findLastIndex(element => element > 10); // 4 (ES2023)

七、类型安全的数组操作(TypeScript特有)

// 1. 类型保护
function processArray(arr: (string | number)[]): string[] {
  // 类型守卫
  return arr.filter((item): item is string => typeof item === "string");
}

// 2. 只读数组
const readOnlyArr: readonly number[] = [1, 2, 3];
// readOnlyArr.push(4); // 错误:push不存在于类型'readonly number[]'

// 3. 元组类型
const tuple: [string, number] = ["Alice", 25];
tuple[0] = "Bob"; // OK
// tuple[2] = "extra"; // 错误:长度为 "2" 的元组类型 "[string, number]" 在索引 "2" 处没有元素

// 4. 使用泛型
function getFirst<T>(arr: T[]): T | undefined {
  return arr[0];
}

const firstNum = getFirst([1, 2, 3]); // number
const firstStr = getFirst(["a", "b"]); // string

// 5. 类型断言
const mixed = ["text", 123, true] as const; // 变成只读字面量类型

八、实用技巧和最佳实践

// 1. 数组去重
const duplicates = [1, 2, 2, 3, 4, 4, 5];
const unique1 = [...new Set(duplicates)]; // [1, 2, 3, 4, 5]
const unique2 = Array.from(new Set(duplicates));

// 对象数组去重
const objects = [{id: 1}, {id: 2}, {id: 1}];
const uniqueObjects = Array.from(
  new Map(objects.map(item => [item.id, item])).values()
);

// 2. 数组分组
const groupBy = <T>(arr: T[], keyFn: (item: T) => string): Record<string, T[]> => {
  return arr.reduce((groups, item) => {
    const key = keyFn(item);
    groups[key] = groups[key] || [];
    groups[key].push(item);
    return groups;
  }, {} as Record<string, T[]>);
};

// 3. 分页功能
function paginate<T>(array: T[], pageSize: number, pageNumber: number): T[] {
  return array.slice((pageNumber - 1) * pageSize, pageNumber * pageSize);
}

// 4. 数组交集、并集、差集
const a = [1, 2, 3];
const b = [2, 3, 4];

const union = [...new Set([...a, ...b])]; // [1, 2, 3, 4]
const intersection = a.filter(x => b.includes(x)); // [2, 3]
const difference = a.filter(x => !b.includes(x)); // [1]

// 5. 安全访问(避免undefined)
const safeGet = <T>(arr: T[], index: number): T | undefined => {
  return arr.at(index); // ES2022的at方法,支持负数索引
};

const lastItem = arr.at(-1); // 最后一个元素
const secondLast = arr.at(-2); // 倒数第二个

九、性能考虑

// 1. 大规模数据使用Set提高查找性能
const largeArray = new Array(1000000).fill(0).map((_, i) => i);
const lookupSet = new Set(largeArray); // O(1)查找

// 2. 避免在循环中修改数组长度
// ❌ 不好
for (let i = 0; i < arr.length; i++) {
  if (arr[i] === 0) {
    arr.splice(i, 1); // 改变长度,需要调整索引
    i--; // 需要手动调整
  }
}

// ✅ 更好
arr = arr.filter(item => item !== 0);

// 或者从后向前遍历
for (let i = arr.length - 1; i >= 0; i--) {
  if (arr[i] === 0) {
    arr.splice(i, 1); // 不会影响前面的索引
  }
}

// 3. 链式调用优化
const result = largeArray
  .filter(x => x % 2 === 0) // 先过滤减少数据量
  .map(x => x * 2)          // 再转换
  .slice(0, 10);            // 最后取部分

十、ES2023+ 新特性

// 1. toReversed / toSorted / toSpliced(ES2023)
const original = [3, 1, 2];
const sorted = original.toSorted(); // [1, 2, 3],original不变
const reversed = original.toReversed(); // [2, 1, 3],original不变
const spliced = original.toSpliced(1, 1, 4); // [3, 4, 2],original不变

// 2. with 方法(ES2023)- 不可变更新
const arr = [1, 2, 3];
const newArr = arr.with(1, 99); // [1, 99, 3],arr不变

// 3. findLast / findLastIndex(ES2023)
const lastEven = [1, 2, 3, 4, 5].findLast(x => x % 2 === 0); // 4
const lastEvenIndex = [1, 2, 3, 4, 5].findLastIndex(x => x % 2 === 0); // 3

总结表

操作类型方法是否修改原数组返回值
添加push, unshift, splice新长度/删除的元素
删除pop, shift, splice删除的元素
修改fill, splice, 直接赋值修改后的数组
查找find, indexOf, includes元素/索引/布尔值
遍历forEach, map, filter, reduce根据方法不同
转换slice, concat, flat, join新数组/字符串
排序sort, reverse排序后的数组
验证some, every布尔值

最佳实践建议

  1. 使用不可变方法(如 map, filter, slice)以避免副作用
  2. 复杂操作考虑使用 reduce 或组合多个方法
  3. TypeScript 中充分利用类型系统,使用泛型增强复用性
  4. 大数据集时注意性能,使用 Set 优化查找
历史留言 (0)
ICP备案号浙ICP备2026065730号-1公安备案号浙公网安备33019202003213号