- 使用 filter 方法(推荐)
// 方法1: 使用filter保留奇数下标元素
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// 删除偶数下标(0, 2, 4, 6, 8...),保留奇数下标
const result1 = arr.filter((_, index) => index % 2 !== 0);
console.log(result1); // [1, 3, 5, 7, 9]
// 或删除奇数下标,保留偶数下标
const result2 = arr.filter((_, index) => index % 2 === 0);
console.log(result2); // [0, 2, 4, 6, 8]
2. 使用 for 循环(原地修改)
// 方法2: 从后向前遍历,原地删除
function removeEvenIndexes(arr) {
// 从后向前遍历,避免索引错乱
for (let i = arr.length - 1; i >= 0; i--) {
if (i % 2 === 0) { // 删除偶数下标
arr.splice(i, 1);
}
}
return arr;
}
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(removeEvenIndexes(arr)); // [1, 3, 5, 7, 9]
console.log(arr); // 原数组也被修改
- 使用 reduce 方法
// 方法3: 使用reduce
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const result = arr.reduce((acc, cur, index) => {
if (index % 2 !== 0) { // 只保留奇数下标
acc.push(cur);
}
return acc;
}, []);
console.log(result); // [1, 3, 5, 7, 9]
- 使用 for 循环创建新数组
// 方法4: 遍历奇数下标创建新数组
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function removeEvenIndexes(arr) {
const result = [];
for (let i = 0; i < arr.length; i++) {
if (i % 2 !== 0) { // 只取奇数下标
result.push(arr[i]);
}
}
return result;
}
console.log(removeEvenIndexes(arr)); // [1, 3, 5, 7, 9]
- while 循环 + splice
// 方法5: 使用while循环
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
function removeEvenIndexes(arr) {
let i = 0;
while (i < arr.length) {
if (i % 2 === 0) { // 删除偶数下标
arr.splice(i, 1);
} else {
i++; // 只有不删除时才递增
}
}
return arr;
}
console.log(removeEvenIndexes(arr)); // [1, 3, 5, 7, 9]
- 性能优化版本(大数据量)
// 方法6: 高性能版本,避免splice
function removeEvenIndexesOptimized(arr) {
const result = [];
const length = arr.length;
// 从第一个奇数下标开始,步长为2
for (let i = 1; i < length; i += 2) {
result.push(arr[i]);
}
return result;
}
// 测试大数据量
const largeArr = Array.from({ length: 1000000 }, (_, i) => i);
console.time('优化版');
const optimizedResult = removeEvenIndexesOptimized(largeArr);
console.timeEnd('优化版'); // 大约 5-10ms
console.log('结果长度:', optimizedResult.length); // 500000
- 原地修改的高效方法
function removeEvenIndexesInPlace(arr) {
let writeIndex = 0;
for (let readIndex = 0; readIndex < arr.length; readIndex++) {
if (readIndex % 2 !== 0) { // 只保留奇数下标
arr[writeIndex] = arr[readIndex];
writeIndex++;
}
}
// 截断数组
arr.length = writeIndex;
return arr;
}
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(removeEvenIndexesInPlace(arr)); // [1, 3, 5, 7, 9]
console.log(arr); // 原数组被修改
- Vue 3 响应式数组处理
<template>
<div>
<h3>原始数组: {{ originalArray }}</h3>
<h3>处理后: {{ processedArray }}</h3>
<button @click="processArray">删除偶数下标</button>
<button @click="resetArray">重置数组</button>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
// 原始响应式数组
const originalArray = ref([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
// 计算属性:删除偶数下标
const processedArray = computed(() => {
return originalArray.value.filter((_, index) => index % 2 !== 0)
})
// 方法处理
const processArray = () => {
// 方法1: 创建新数组(推荐,不修改原数组)
originalArray.value = originalArray.value.filter((_, index) => index % 2 !== 0)
// 方法2: 原地修改(会触发响应式更新)
// let writeIndex = 0
// for (let i = 0; i < originalArray.value.length; i++) {
// if (i % 2 !== 0) {
// originalArray.value[writeIndex] = originalArray.value[i]
// writeIndex++
// }
// }
// originalArray.value.length = writeIndex
}
const resetArray = () => {
originalArray.value = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
</script>
- 通用工具函数
// 工具函数集合
const ArrayUtils = {
/**
* 删除偶数下标元素
* @param {Array} arr - 输入数组
* @param {boolean} inPlace - 是否原地修改
* @returns {Array} 处理后的数组
*/
removeEvenIndexes: function(arr, inPlace = false) {
if (!Array.isArray(arr)) {
throw new TypeError('输入必须是数组')
}
if (inPlace) {
return this._removeEvenIndexesInPlace(arr)
} else {
return this._removeEvenIndexesNew(arr)
}
},
/**
* 创建新数组(不修改原数组)
*/
_removeEvenIndexesNew: function(arr) {
return arr.filter((_, index) => index % 2 !== 0)
},
/**
* 原地修改
*/
_removeEvenIndexesInPlace: function(arr) {
let writeIndex = 0
for (let i = 0; i < arr.length; i++) {
if (i % 2 !== 0) {
arr[writeIndex] = arr[i]
writeIndex++
}
}
arr.length = writeIndex
return arr
},
/**
* 删除奇数下标元素
*/
removeOddIndexes: function(arr, inPlace = false) {
if (inPlace) {
let writeIndex = 0
for (let i = 0; i < arr.length; i++) {
if (i % 2 === 0) {
arr[writeIndex] = arr[i]
writeIndex++
}
}
arr.length = writeIndex
return arr
} else {
return arr.filter((_, index) => index % 2 === 0)
}
},
/**
* 删除指定下标的元素
* @param {Array} arr - 输入数组
* @param {Function} condition - 条件函数,返回true则删除
*/
removeByIndexCondition: function(arr, condition, inPlace = false) {
if (inPlace) {
let writeIndex = 0
for (let i = 0; i < arr.length; i++) {
if (!condition(i)) {
arr[writeIndex] = arr[i]
writeIndex++
}
}
arr.length = writeIndex
return arr
} else {
return arr.filter((_, index) => !condition(index))
}
}
}
// 使用示例
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// 删除偶数下标
console.log(ArrayUtils.removeEvenIndexes(arr)) // [1, 3, 5, 7, 9]
console.log(arr) // 原数组不变 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// 原地修改
console.log(ArrayUtils.removeEvenIndexes(arr, true)) // [1, 3, 5, 7, 9]
console.log(arr) // 原数组被修改 [1, 3, 5, 7, 9]
// 删除奇数下标
const arr2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(ArrayUtils.removeOddIndexes(arr2)) // [0, 2, 4, 6, 8]
// 自定义条件
const arr3 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(ArrayUtils.removeByIndexCondition(
arr3,
index => index % 3 === 0
)) // 删除下标是3的倍数的元素
- ES6+ 高级写法
// 使用生成器函数
function* filterByIndex(arr, condition) {
for (let i = 0; i < arr.length; i++) {
if (condition(i)) {
yield arr[i]
}
}
}
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
const result = [...filterByIndex(arr, i => i % 2 !== 0)]
console.log(result) // [1, 3, 5, 7, 9]
// 使用箭头函数和三元运算符
const removeEvenIndexes = arr => arr.filter((_, i) => i % 2 ? arr[i] : null).filter(Boolean)
// 使用位运算(性能更好)
const removeEvenIndexesBit = arr => {
const result = []
for (let i = 1; i < arr.length; i += 2) {
result.push(arr[i])
}
return result
}
// 使用 Array.from
const removeEvenIndexesFrom = arr =>
Array.from(
{ length: Math.ceil(arr.length / 2) },
(_, i) => arr[i * 2 + 1]
).filter(Boolean)
- TypeScript 版本
// TypeScript 类型安全的版本
class ArrayProcessor {
/**
* 删除偶数下标元素
* @param arr 输入数组
* @param inPlace 是否原地修改
* @returns 处理后的数组
*/
static removeEvenIndexes<T>(arr: T[], inPlace: boolean = false): T[] {
if (inPlace) {
return this.removeEvenIndexesInPlace(arr)
} else {
return this.removeEvenIndexesNew(arr)
}
}
private static removeEvenIndexesNew<T>(arr: T[]): T[] {
return arr.filter((_, index) => index % 2 !== 0)
}
private static removeEvenIndexesInPlace<T>(arr: T[]): T[] {
let writeIndex = 0
for (let i = 0; i < arr.length; i++) {
if (i % 2 !== 0) {
arr[writeIndex] = arr[i]
writeIndex++
}
}
arr.length = writeIndex
return arr
}
/**
* 泛型方法:根据下标条件过滤数组
*/
static filterByIndex<T>(
arr: T[],
predicate: (index: number) => boolean
): T[] {
return arr.filter((_, index) => predicate(index))
}
}
// 使用示例
const numbers: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
const strings: string[] = ['a', 'b', 'c', 'd', 'e', 'f']
console.log(ArrayProcessor.removeEvenIndexes(numbers)) // [1, 3, 5, 7, 9]
console.log(ArrayProcessor.filterByIndex(strings, i => i % 2 === 0)) // ['a', 'c', 'e']
- 性能对比测试
// 性能测试
function testPerformance() {
const largeArray = Array.from({ length: 1000000 }, (_, i) => i)
// 测试 filter 方法
console.time('filter')
const result1 = largeArray.filter((_, i) => i % 2 !== 0)
console.timeEnd('filter')
// 测试 for 循环
console.time('for loop')
const result2 = []
for (let i = 1; i < largeArray.length; i += 2) {
result2.push(largeArray[i])
}
console.timeEnd('for loop')
// 测试 while 循环
console.time('while loop')
const arrCopy = [...largeArray]
let i = 0
while (i < arrCopy.length) {
if (i % 2 === 0) {
arrCopy.splice(i, 1)
} else {
i++
}
}
console.timeEnd('while loop')
// 测试 reduce
console.time('reduce')
const result4 = largeArray.reduce((acc, cur, i) => {
if (i % 2 !== 0) acc.push(cur)
return acc
}, [])
console.timeEnd('reduce')
}
testPerformance()
// 结果通常: for loop 最快, filter 次之, reduce 较慢, while+splice 最慢
总结
推荐方法:
-
最简洁:filter方法
arr.filter((_, i) => i % 2 !== 0)
-
最高性能:for循环
const result = []
for (let i = 1; i < arr.length; i += 2) {
result.push(arr[i])
}
-
原地修改:使用写指针
let writeIndex = 0
for (let i = 0; i < arr.length; i++) {
if (i % 2 !== 0) {
arr[writeIndex] = arr[i]
writeIndex++
}
}
arr.length = writeIndex
注意事项:
-
索引从0开始:JavaScript 数组下标从0开始
-
避免splice:在循环中使用
splice会改变数组长度,容易出错
-
性能考虑:大数据量时避免使用
splice和 filter链式调用
-
不变性:根据需求选择是否修改原数组
扩展应用:
- 删除奇数下标:
i % 2 === 0
- 删除特定模式:
i % 3 === 0删除3的倍数下标
- 保留特定范围:
i >= 2 && i <= 5
**