数组及其应用

486 阅读5分钟

数组

数组用于存放多个数据

创建一个数组

  1. new Array(长度)

长度,数组里面的数据总数,长度一定是一个非负整数

new Array(数据, 数据, 数据...)

创建一个数组,并初始化其每一项的值

数组项:数组其中的一项数据

  1. [数据, 数据, 数据, ...]

创建一个数据,并初始化其每一项的值

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // var arr = new Array(20); //创建了一个长度为20的数组

       //console.log(arr)         //[empty x 20]
        //创建一个长度为5,数据分别是1, 5, 354, 234, 11
        // var arr = new Array(1, 5, 354, 234, 11)
        // console.log(arr);    //[1, 5, 354, 234, 11]

        //创建一个长度为5,数据分别是1, 5, 354, 234, 11
        // var arr = [1, 5, 354, 234, 11];
        // console.log(arr);              //[1, 5, 354, 234, 11]
        var arr = [34, "asdf", true, null, undefined, {
            x: 3,
            y: 44
        }];
        console.log(arr);     //[34, "asdf", true, null, undefined, {x: 3, y: 44}]
    </script>
</body>
</html>

认识数组的本质

数组的本质是一个对象

  • length属性: 数组的长度,会自动变化,值为最大下标+1
  • 数字字符串属性: 叫做下标,也叫做索引,相当于数组中每个数据的编号,下标从0开始排列

连续下标的取值范围:0~length - 1, 如果给length直接赋值,会导致数组可能被截断

实际开发中,不要给length赋值。


// var arr = [1, 2, "qwer", true, null];
// console.log(arr, typeof arr, arr.length);     //[1, 2, "qwer", true, null], "object", 5
var arr = [34, "asdf", true, null, undefined, {
            x: 3,
            y: 44
        }];
console.log(arr[5].x, arr[5].y);     //3, 34

var arr = [3, 6, 9, 13];
arr[0] = 10;
arr["0"] = 5;
console.log(arr[0], arr["0"]);     //5, 5

var arr = [3, 6, 22, 5, 33, 66, 88];
arr.length = 2;
console.log(arr)      //[3, 6]

下标

通常情况下,下标是连续的。

下标不连续的数组,叫做稀松数组。


var arr = [, , , 100];
console.log(arr);     //[empty x 3, 100];

数组的常见操作

添加数组项

  • 数组[长度] = 数据:向数组末尾添加一个数据
  • 数组.push(数据):向数组末尾添加一个数据
  • 数组.unshift(数据):向数组起始位置添加一个数据,会导致数组每一项的下标向后移动
  • 数组.splice(下标, 0, 添加的数据): 从指定下标位置开始,删除0个,然后在该位置插入添加的数据,如果下标超过范围,则按照范围的边界进行处理。

push、 unshift、 splice 可以添加多个数据

<script>
        //向末尾添加一项
        var arr = [23, 345, 5, 234, 88];
        // arr[5] = "sdfgg";   //向末尾添加一项
        // arr[arr.length] = "asdghff";  //向末尾添加一项
        // arr[arr.length] = "asdghff1";  //向末尾添加一项
        // arr[arr.length] = "asdghff2";  //向末尾添加一项
        // console.log(arr);    //[23, 345, 5, 234, 88, "sdfgg", "asdghff", "asdghff1" "asdghff2"]
        arr.push("abc");
        arr.push("bcd");
        arr.push({x:1, y:2});
        console.log(arr);  //[23, 345, 5, 234, 88, "abc", "bcd", {x:1,y:2}]

        var arr = [1, 2, 3];
        //向起始位置添加一项
        arr.unshift(22);
        console.log(arr);    //[22, 1, 2, 3]

        //向指定位置插入数据
        // arr.splice(2, 0, "ab", "bc");
        arr.splice(10, 0, "ab", "bc");
        // console.log(arr);   //[1, 2, "ab", "bc", 3]
        console.log(arr);    //["ab", "bc", 1, 2, 3]

    </script>

删除数据

  • delete 数组[下标]: 这种做法不会导致数组其他的属性发生变化,因此,该做法会导致产生稀松数组,所以不推荐使用该做法。
  • 数组.pop(): 删除数组的最后一项,该表达式返回最后一项的数据
  • 数组.shift(): 删除数组的第一项,该表达式返回数组第一项的数据
  • 数组.splice(下标, 删除的数量, 添加的数据): 从指定下标位置开始,删除指定数量,然后在该位置插入添加的数据,如果下标超过范围,则按照范围的边界进行处理。该表达式返回一个新数组,该数组记录被删除的数据。
<script>
        
    var arr = [1, 2, 3, 4];
    //删除数据
    delete arr[1];
    console.log(arr);    //[1, empty, 3, 4]

    //删除数组最后一项
    var n = arr.pop();
    console.log(arr, n);    //[1, 2, 3], 4

    //删除数组第一项
    var m = arr.shift();
    console.log(arr, m);     //[2, 3, 4], 1

    //如果是一个空数组
    var arr1 = []
    var j = arr1.shift();
    console.log(arr1, j);    //[], 返回undefined

    //删除指定位置
    var k = arr.splice(1, 2);
    console.log(arr. k);    //[1, 4], [2, 3]
    
    //删除数量超过界限
    var k = arr.splice(1, 1000);
    console.log(arr, k);    //[1], [2, 3, 4]  

</script>

其他操作

  • 数组.slice(起始位置下标, 结束位置下标):将起始位置到结束位置之间的数据拿出来,得到一个新的数组,该函数不会改变原数组;注意:结束下标取不到

下标可以写负数,如果是负数,则从数组的末尾开始计算

如果不写结束下标,则直接取到末尾

<script>
    //slice,不含结束下标
    var arr = [1, 2, 3, 4, 5, 6];
    var newArr = arr.slice(3, 5);
    console.log(arr, newArr);   //[1, 2, 3, 4, 5, 6], [4, 5]
    //slice,下标为负数
    var arr = [1, 2, 3, 4, 5, 6];
    var newArr = arr.slice(-4, -1);  //从倒数第四个到倒数第一个[3,4,5]
    var newArr = arr.slice(-4, 0);  //只能从做到右,所以该表达式取出的是空数组[]
    var newArr = arr.slice(-4, arr.length);  //取最后四个[3,4,5,6]
    console.log(arr, newArr);   //[1,2,3,4,5,6]
</script>
  • 数组清空

数组.splice(0, 数组.length);

数组.length = 0;

<script>
    var arr = [1, 2, 3, 4, 5];
    // arr.splice(0, arr.length);
    arr.length = 0;
    console.log(arr);  //[]
</script>
  • 查找数组中某一项的下标

数组.indexOf(数据)

从数组中依次查找对应的数据,查找时使用严格相等进行比较。找到第一个匹配的下标,返回。如果没有找到,则返回-1

数组.lastIndexOf(数据)

功能和indexOf类似,只是查找的是最后一个匹配的下标

  • 数组.fill()

数组.fill(数据):将数组的所有项,填充为指定的数据

数组.fill(数组,开始下标):将数组从开始下标起,到数组的末尾,填充为指定的数据

数组.fill(数组, 开始下标, 结束下标):将数组从开始下标起,到数组的结束下标(取不到),填充为指定的数据

<script>
    var arr = [1, 2, 3, 4, 5];
    var index = arr.indexOf(3);
    var index1 = arr.indexOf("3");
    var noindex = arr.indexOf(6);
    console.log(index, index1, noindex);    //2, -1, -1
</script>

新语法补充

in关键字

判断某个属性在对象中是否存在

属性名 in 对象

<script>
    // var obj = {
    //     a: 23,
    //     b: 32,
    //     c: 'ddfsfsf'
    // };
    // console.log("a" in obj);   //true
    var arr = [2, 23, 24, 25];
    console.log(arr);
    console.log(23 in arr);  //false  判断的是某个属性是否存在
</script>

for-in 循环

for (var prop in 对象) {
    //循环体
}

取出对象的所有属性名,每次循环将其中一个属性名赋值给变量prop,运行循环体

<script>
    //对象遍历
    var obj = {
        a: 1,
        b: 23,
        c: "fsfgfsg"
    };
    
    for(var prop in obj) {
        console.log(prop);   //a,b,c
    }
    
    //利用该特点,可以实现数组遍历
    var arr = ["qaz", "wsx", "edc", "rfv", 1, 2, 3];
    for (var prop in arr) {
        console.log(prop, arr[prop]);   //0 "qaz", 1 "wsx", 2 "edc", 3 "rfv", 4 1, 5 2, 6 3
    }

    //创建一个长度为100的数组,给数组的每一项赋值为“abc”
    var arr = new Array(100);
    // for-in循环
    for (var index in arr) {
        arr[index] = "abc"
    }
    console.log(arr);    //[empty × 100]
    //in
    for (var i = 0; i < arr.length; i++) {
        arr[i] = "abc"
    }
    console.log(arr);   //["abc", "abc", "abc", ...]
    //fill()
    arr.fill("abc");
    console.log(arr);   //["abc", "abc", "abc", ...]
</script>

数组应用

数组的本质:对象(引用类型)

<script>
    var arr1 = [2, 3, 5, 7];   //arr1中存放的是地址
    var arr2 = arr1;   //arr2中存放的是地址
    arr2[0] = 5;
    console.log(arr1[0], arr2[0]);    //5 5
</script>

如何复制(克隆,产生一个全新的对象)

<script>
    var arr1 = [2, 3, 5, 7];
    var arr2 = arr1.slice();
    arr2[0] = 5;
    console.log(arr1 === arr2);   //false
    console.log(arr1[0], arr2[0]); //2 5
</script>

对数组求和

<script>
    var arr = [23, 34, 45, 56, 78];
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        sum += arr[i];
    }
    console.log(sum);   //236
</script>

对二维数组进行求和

<script>
    //二维数组:数组中的每一项是一个数组

    //3*3的二维数组
    var arr = [
        [1, 2, 3],
        [22, 33, 44],
        [222, 333, 444]
    ];
    
    //输出二维数组的每一项
    for (var i = 0; i < arr.length; i++) {
        var subArr = arr[i];
        for (var j = 0; j < subArr.length; j++) {
            console.log(subArr[j]);   //1 2 3 22 33 44 222 333 444
        }
    }

    //对二维数组求和

    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        for (var j = 0; j < arr[i].length; j++) {
            sum += arr[i][j];
        }
    }
    console.log(sum)   //1104

</script>

将数组的每一项进行字符串拼接

<script>
    //将数组的每一项进行字符串拼接

    var arr = [2, 4, 5, 6, 7, 88];

    //输出数组中的每一项
    var str = ""
    for (var i = 0; i < arr.length; i++) {
        //console.log(arr[i]);
        str += arr[i];
        if (i < arr.length - 1) {
             str += ",";     
        }
    }
    console.log(str);

    //数组.join(分隔符),该函数返回一个字符串
    var str = arr.join(",");
    console.log(str);   // 2,4,5,6,7,88
</script>

拼接数组

<script>
    var arr1 = [34, 5, 2, 1];
    var arr2 = ["abc", "asd", "zxc"];
    //数组1.concat(数组2)
    //将数组2的所有元素 拼接到 数组1 的末尾,产生一个新数组返回,该表达式不会对元素组造成任何影响
    var newArr = arr1.concat(arr2);
    console.log(newArr); //[34, 5, 2, 1, "abc", "asd", "zxc"]
</script>

题目分析

  1. 提示用户输入数组的长度,以及数组每一项的值,然后输出该数组
<script>
    var len = +prompt("请输入数组的长度:");
    if (isNaN(len) || len < 0) {
        console.log("输入有误");

    } else {
        //输入正确
        var arr = new Array(len);
        for (var i = 0; i < len; i++) {
            //提示用户输入数组的这一项的值
            arr[i] = prompt("请输入数组第" + (i + 1) + "项的值");
        }
        console.log(arr);
    }
</script>

  1. 初始化一个数字数组,然后输出数组中所有的奇数
<script>
    var arr = [233, 234, 235, 236, 237];
    for (var index in arr) {
        if (arr[index] % 2 !== 0) {
            console.log(arr[index]);  //233, 235, 237
        }
    }
</script>

  1. 初始化一个数字数组,然后输出数组中所有的素数
<script>
    var arr = [234, 4, 23, 211, 23];
    for (var index in arr) {
        //判断arr[index]是不是素数
        var isFind = false;
        for (var i = 2; i < arr[index] - 1; i++) {
            if (arr[index] % i === 0) {
                isFind = true;
                break;
            }
        }
        if (!isFind && arr[index] >= 2) {
            console.log(arr[index]);
        }
    }
</script>

  1. 斐波拉契数列是这样一种数列: 1 1 2 3 5 8 13 ...... 数列前两位为1,第n位=第n-1位+第n-2位 让用户输入斐波拉契数列的长度,在控制台中打印该长度的斐波拉契数列,效果如下:
<script>
    var len = +prompt("请输入斐波拉契数列的长度");
    if (isNaN(len) || len < 0) {
        console.log("输入有误");
    } else {
        //输入正确
        var arr = [];
        for (var i = 0; i < len; i++) {
            if (i === 0 || i === 1) {
                arr[i] = 1;
            } else {
                arr[i] = arr[i - 1] + arr[i - 2];
            }
        }

        console.log(arr);
    }
</script>

  1. 定义一个用户数组,数组的每一项是一个用户对象,用户对象中包含账号和密码,随意初始化 一些对象放入数组中。然后提示用户输入账号和密码,判断是否登录成功
<script>
    var users = [
        {
            loginId: "asdf",
            loginPwd: "123456"
        },
        {
            loginId: "asdf1",
            loginPwd: "1234"
        },
        {
            loginId: "asdf2",
            loginId: "12345"
        },
        {
            loginId: "asdf3",
            loginId: "123"
        }
    ];
    var loginId = prompt("请输入账号:");
    var loginPwd = prompt("请输入密码:");

    
    //查找问题
    var isFind = false;
    for (var i = 0 ; i < users.length; i++) {
        var u = users[i];
        if (u.loginId === loginId && u.loginPwd === loginPwd) {
            isFind = true;
            break;
        }
    }
    if (isFind) {
        console.log("登录成功");
    } else {
        console.log("登录失败")
    }

</script>

  1. 初始化一个5*5的二维数组,数组每一项是一个数字,计算对角线之和
<script>
    var arr = [
        [1, 2, 3, 4, 5],
        [6, 7, 8, 9, 0],
        [1, 3, 5, 7, 9],
        [2, 4, 6, 8, 0],
        [1, 4, 7, 9, 3]
    ];
    //求对角线之和
    var sum = 0;
    for (var i = 0; i < arr.length; i++) {
        //arr[i]是一个数组
        for (var j = 0; j < arr[i].length; j++) {
            //arr[i][j]
            if (i === j || i + j === arr.length - 1) {
                sum += arr[i][j];
            }
        }
    }
    console.log(sum);
</script>

  1. 初始化一个数字数组(数据随意),对该数组进行升序排序,然后输出结果

思路提示:

数组的排序有多种算法可以完成,这里介绍其中一种:冒泡排序算法

冒泡排序算法的原理如下:

  • 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  • 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数
  • 针对所有的元素重复以上的步骤,除了已排好序的元素。

<script>
    /*
        23, 3, 44, 5, 8, 1
    */
    var arr = [23, 3, 44, 5, 8, 1];
    for (var i = 1; i < arr.length; i++) {
        //  第i次排序
        for (var j = 0; j < arr.length - i; j++) {
            //比较j和j+1两个位置的数字
            if (arr[j] > arr[j + 1]) {
                //交换
                var temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    console.log(arr);
</script>

  1. 有一个数组,存放了一些数字,找出出现频率最高的数字

<script>
    var arr = [1,2,2,3,3,3,4,4,4,4,5,5,5,5,5,5,6,7,8];
    //输出: 5频率最高,出现6次
    //得到记录对象
    var record = {};   //记录对象
    for (var i = 0; i < arr.length; i++) {
        var n = arr[i];
        if (record[n]) {
            record[n] ++;
        } else {
            record[n] = 1;
        }
    }
    var result;     //结果对象
    for (var prop in record) {
        if (!result || record[prop] > result.frequency) {
            result = {
                number: prop,
                frequency: record[prop]
            }
        }
    }
    console.log(`${result.number}出现频率最高,出现${result.frequency}次`);

</script>