JavaScript中数组的方法和运用

991 阅读11分钟

索引

数组的索引是用来标识数组中元素位置的数字。在 JavaScript 中,数组的索引从 0 开始,即第一个元素的索引为 0,第二个元素的索引为 1,以此类推。例如,数组 [1, 2, 3, 4, 5] 中,元素 1 的索引是 0,元素 2 的索引是 1,元素 3 的索引是 2,以此类推。

索引可以用来访问数组中的元素,例如 array[0] 表示数组 array 的第一个元素,array[1] 表示数组的第二个元素,依此类推。

let arr = [1, 2, 3, 4, 5];
console.log(arr[0]); // 输出 1
console.log(arr[2]); // 输出 3

数组的方法

JavaScript中的数组具有丰富的方法,用于执行各种操作。以下是一些常见的数组方法:

1. push() : 向数组的末尾添加一个或多个元素,可以返回新数组的长度。

  let arr = [1, 2, 3, 4, 5];
  let newLength = arr.push(6);//添加一个元素到末尾
  console.log(newLength);//返回新数组的长度,输出 6
  console.log(arr);//输出[1, 2, 3, 4, 5, 6]

  arr.push(8,9);//添加多个元素到末尾
  console.log(arr);//输出[1, 2, 3, 4, 5, 6, 8, 9]
  1. pop() : 移除数组内的最后一个元素,可以返回数组的最后一个元素也就是被移除的那个元素。
   let arr = [1, 2, 3, 4, 5];
   let removedElement = arr.pop();//移除数组内的最后一个元素 5
   console.log(removedElement);//返回数组的最后一个元素,输出 5
   console.log(arr);//输出[1, 2, 3, 4]
  1. unshift() : 向数组的开头添加一个或多个元素,可以返回新数组的长度。
 let arr = [1, 2, 3, 4];
 let newLength = arr.unshift(0); // 添加一个元素到数组的开头
 console.log(newLength);//返回新数组的长度,输出 5
 console.log(arr); // 输出 [0,1,2,3,4]

 arr.unshift(-2, -1); // 添加多个元素到数组的开头
 console.log(arr); // 输出 [-2, -1, 0, 1, 2, 3, 4]
  1. shift() : 移除数组的第一个元素并返回该元素的值。同时,它也会修改原始数组,使得数组的长度减一,索引重新排序。

    let arr = [1, 2, 3, 4];
    let firstElement = arr.shift(); // 移除数组的第一个元素 1,返回它的值
    console.log(firstElement); // 返回第一个元素的值,输出 1
    console.log(arr); // 输出 [2, 3, 4]
    
  2. indexOf() : 返回指定元素在数组中第一次出现的位置,如果不存在则返回-1。

    let arr = [2, 3, 9, 2];
    console.log(arr.indexOf(2)); // 输出 0,因为指定元素 2 第一次出现的位置是索引为 0 的时候
    console.log(arr.indexOf(7)); // 输出 -1,因为数组中不存在 7
    console.log(arr.indexOf(2,2)); //输出 3,从索引 2 开始查找第一个 2
    

    在这个例子中,indexOf(2) 返回 0,因为数组中第一个出现 2 的索引为 0 。而 indexOf(7) 返回 -1,因为数组中不存在元素 7

  3. splice() : 从数组中添加或移除元素,可以用于在指定位置添加或删除元素,并返回被删除的元素组成的数组。它可以同时修改原始数组。

    splice() 方法的语法是:

    arr.splice(start, deleteCount, item1, item2, ...)
    
    • start 是要开始添加或删除的位置的索引。
    • deleteCount 是要删除的元素个数。如果设置为 0,则不会删除任何元素。
    • item1, item2, ... 是要添加到数组的元素。

    例如:

    let arr = [1, 2, 3, 4, 5];
    arr.splice(1, 2); // 从索引 1 开始删除 2 个元素
    console.log(arr); // 输出 [1, 4, 5]
    
    arr.splice(2, 0, 8, 9); // 从索引 2 开始删除 0 个元素,并添加 8 和 9
    console.log(arr); // 输出 [1, 4, 8, 9, 5]
    
    arr.splice(1, 1, 6, 7, 5); // 从索引 1 开始删除 1 个元素 4 ,并添加 6 、 7 、5
    console.log(arr); // 输出 [1, 6, 7, 5, 8, 9, 5]
    

    在第一个例子中,splice(1, 2) 从索引为 1 的位置开始删除了 2 个元素,即删除了数组中的 23。在第二个例子中,splice(2, 0, 8, 9) 从索引为 2 的位置开始不删除元素,但是添加了 89。在第三个例子中,splice(1, 1, 6, 7,5) 从索引为 1 的位置开始删除了 1 个元素,但是添加了 675

  4. join() : 将数组中所有元素连接成一个字符串,并返回这个字符串。

    let arr = ['是', '昔年', '啊'];
    let result = arr.join('');
    console.log(result); // 输出 "是昔年啊"
    
    let arr1 = ['apple', 'banana', 'orange'];
    let result1 = arr1.join(', ');
    console.log(result1); // 输出 "apple, banana, orange"
    
    let numbers = [1, 2, 3];
    let result2 = numbers.join(' - ');
    console.log(result2); // 输出 "1 - 2 - 3"
    

    在第一个例子中,join() 方法将数组 arr 中的元素连接成一个字符串,返回结果为 "是昔年啊"。在第二个例子中,join() 方法将数组 arr1 中的元素用逗号和空格, 连接成一个字符串,返回结果为 "apple, banana, orange"。在第三个例子中,join() 方法将数组 numbers 中的元素使用连字符连接成一个字符串,返回结果为 "1 - 2 - 3"。

    需要注意的是,join() 方法不会改变原始数组,它只是返回一个新的字符串。

  5. forEach() : 它是一个迭代器函数,用于遍历数组,对每个元素执行指定操作。

    let arr = [1, 2, 3, 4, 5];
    arr.forEach(function(element) {
      console.log(element);
    });
    

    image.png

    在这个例子中,forEach() 方法遍历了数组 arr 中的每个元素,并对每个元素执行了一个函数,该函数会将元素输出到控制台。这样就会依次输出数组中的每个元素。

    forEach() 方法适用于需要遍历数组但不需要返回新数组的情况。如果你需要对数组的每个元素进行操作,并且想要返回一个新的数组,可以考虑使用 map() 方法。

  6. map() : 在 JavaScript 中,map() 是数组的一个高阶函数,遍历数组,对数组中的每个元素执行指定的操作,并返回一个新的数组,该数组包含每个元素的操作结果。

    let arr = [1, 2, 3, 4, 5];
    let add = arr.map(function(num) {
      return num += 2;
    });
    
    console.log(add); // 输出 [3, 4, 5, 6, 7]
    console.log(arr); // 输出 [1, 2, 3, 4, 5],不改变原始数组的值
    

    在这个例子中,map() 方法遍历了数组 arr 中的每个元素,并对每个元素执行了一个函数,将该元素加 2。最终返回了一个新的数组 add,其中包含了每个元素加 2 后的结果。

    使用 map() 方法可以非常方便地对数组中的每个元素进行操作,并且生成一个新的数组,而不改变原始数组。

  7. includes() : 判断数组是否包含某个元素,返回布尔值。

includes() 方法的语法如下:

arr.includes(searchElement[, fromIndex])
  • searchElement 是要查找的元素。
  • fromIndex 是可选参数,表示开始搜索的位置,默认为 0。

例如:

let arr = [1, 2, 3, 4, 5];

console.log(arr.includes(3)); // 输出 true,因为数组中包含元素 3
console.log(arr.includes(6)); // 输出 false,因为数组中不包含元素 6
console.log(arr.includes(2, 2)); // 输出 false,因为从索引 2开始找不到 2

在这个例子中,arr.includes(3) 返回 true,因为数组 arr 中包含元素 3。而 arr.includes(6) 返回 false,因为数组 arr 中不包含元素 6arr.includes(2,2)返回 false,这句代码的意思是从索引 2 开始查找元素 2 ,索引 2 之后组成的数组为[3, 4, 5],没有元素 2 ,所以返回false

includes() 方法可以方便地判断数组中是否包含某个元素,返回布尔值表示结果。

  1. slice() : 返回数组的一部分,不会修改原始数组。
const fruits = ['apple', 'banana', 'strawberry', 'peach', 'pear'];

console.log(fruits.slice(1, 3)); // 输出: ['banana', 'strawberry']

在这个例子中,slice(1, 3) 提取从索引 1 开始到索引 3(不包括 3)的元素,组成一个新数组,结果是 ['banana', 'strawberry']

  1. concat() : 将两个或多个数组合并成一个新数组。
const arr1 = ['a', 'b', 'c'];
const arr2 = [1, 2, 3];
const arr3 = ['g', 'h', 'i'];

const newArray = arr1.concat(arr2, arr3);
console.log(newArray); // 输出: ['a', 'b', 'c', 1, 2, 3, 'g', 'h', 'i']

在这个例子中,concat 方法连接了 array1array2array3,生成了一个新的数组 newArray,其中包含了所有三个数组的元素。

  1. reverse() : 颠倒数组中元素的顺序。这个方法会改变原始数组,而不是创建一个新的数组。
let arr = [1, 2, 3, 4, 5];
arr.reverse();
console.log(arr); // 输出: [5, 4, 3, 2, 1]
  1. sort() : 对数组元素进行排序。如果不传递参数,它会按照字符串Unicode码点的顺序进行排序。也可以传递一个比较函数作为参数,以指定排序的规则。
let arr = [3, 1, 4, 1, 5, 9, 2, 6, -1];
arr.sort();
console.log(arr); // 输出: [-1, 1, 1, 2, 3, 4, 5, 6, 9]

在上面的例子中,数组元素按照默认的字符串Unicode码点进行了排序。

如果要根据数字的大小进行排序,你可以传递一个比较函数作为参数:

let arr = [3, 1, 4, 1, 5, 9, 2, 6, -1];
arr.sort(function(a, b) {
  return b - a;
});
console.log(arr); // 输出: [9, 6, 5, 4, 3, 2, 1, 1, -1]

在这个例子中,传递的比较函数返回 b - a,这表示按降序排列。如果你想要升序排列,可以返回 a - b

数组的运用

看完上面数组的一些常见的方法,是不是觉得很简单,那我们来将数组运用到解题中来。下面是一道简单题LeetCode第一题两数之和

image.png

方法一:暴力枚举

// 定义函数 twoSum,接受 nums 和 target 作为参数
var twoSum = function(nums, target) {
    // 第一个循环遍历数组,i 为第一个加数的索引
    for(let i = 0; i < nums.length; i++ ){
        // 第二个循环从第一个加数的下一个元素开始,j 为第二个加数的索引
        for(let j = i + 1;j < nums.length;j++){
            // 如果找到两个数的和等于目标值
            if(nums[i] + nums[j] === target){
                // 返回这两个数的索引
                return [i, j];
            }
        }           
    }  
};

这段代码采用了暴力解法,其思路是遍历数组中的每一对元素,判断它们的和是否等于目标值。具体解释如下:

  1. 外层循环遍历数组中的每一个元素,i 为第一个加数的索引。
  2. 内层循环从外层循环的下一个元素开始,j 为第二个加数的索引,这样可以避免重复计算。
  3. 对于每一对元素,判断它们的和是否等于目标值 target,如果是,则返回它们的索引。
  4. 如果遍历完数组仍然没有找到满足条件的两个数,则返回空数组或者 null

这种方法实现简单,直观易懂,适用于小规模的数据集。然而,由于嵌套了两层循环,其时间复杂度为 O(n^2),在数组较大时可能性能不佳。

方法二:用数组中indexOf方法

// 定义函数 twoSum,接受 nums 和 target 作为参数
var twoSum = function (nums, target) {
    // 遍历数组 nums
    for (var i = 0; i < nums.length; i++){
        // 计算与当前元素匹配的目标值
        var result = target - nums[i];
        // 在当前元素后面的子数组中查找 result 的索引
        var a = nums.indexOf(result, i + 1);
        // 如果找到了匹配的值,返回两个数的下标
        if (a !== -1){
            return [a, i];
        }
    }
};

这段代码之所以也采用暴力解法,是因为其实现简单直观,适用于一般情况。其思路是遍历数组中的每个元素,然后在剩余的子数组中查找是否存在与当前元素之和为目标值的另一个元素。由于假设只有一个解,所以可以在找到解后立即返回,不需要继续遍历。然而,这种方法的时间复杂度较高,为 O(n^2),因为嵌套了两层循环。

方法三:哈希法

// 定义函数 twoSum,接受 nums 和 target 作为参数
var twoSum = function (nums, target) {
    // 创建一个空对象用于存储差值及其对应的索引
    var diff = {};
    
    // 遍历数组 nums
    for (var i = 0; i < nums.length; i++){
        // 计算与当前元素匹配的目标值
        var complement = target - nums[i];
        
        // 如果在差值对象中找到了与当前元素匹配的值
        if (diff[nums[i]] !== undefined){
            // 返回两个数的下标,其中较小的是差值对应的索引,较大的是当前元素的索引
            return [diff[nums[i]], i];
        }
        
        // 将当前元素与其索引添加到差值对象中
        diff[complement] = i;
    }
};

这段代码采用了一种更高效的方法来解决问题。它使用了哈希表(JavaScript 中的对象)来存储数组中的元素及其对应的索引。具体解释如下:

  1. 首先创建一个空对象 diff,用于存储目标值与当前元素的差值及其对应的索引。
  2. 遍历数组 nums,对于每个元素,计算与目标值的差值 complement
  3. 如果在差值对象中找到了与当前元素匹配的值(即 nums[i]diff 中存在),说明找到了一对满足条件的元素,直接返回它们的下标。
  4. 如果没有找到匹配的值,则将当前元素及其索引添加到差值对象中,以便后续的查找。
  5. 因为哈希表的查找是常数时间复杂度的操作,所以整体的时间复杂度为 O(n)。