目录

🧭 JavaScript 数组方法应用实例

# split() / join()

# 转换短划线命名为驼峰命名

编写函数 camelize(str) 。即:删除所有短横线,并将短横线后的每一个单词的首字母变为大写。例如 my-short-string 转换为 myShortString

相关用例:

camelize("background-color") == 'backgroundColor';
camelize("list-style-image") == 'listStyleImage';
camelize("-webkit-transition") == 'WebkitTransition';
1
2
3
点击查看
function camelize(str) {
    return str.split('-').map((item, index)=> index === 0 ? item : item[0].toUpperCase() + item.slice(1)).join('')
}
1
2
3

涉及关键字 split / map / toUpperCase / join

# 拓展的 Calculator

实现两部分功能:

  • calculate(str) 方法,该方法接受像 "1 + 2" 这样格式为 “数字 运算符 数字”(以空格分隔)的字符串,并返回结果。该方法需要能够理解加号 + 和减号 -

    let calc = new Calculator;
    console.log( calc.calculate("3 + 7") ); 
    
    1
    2
  • 添加方法 addMethod(name, func) ,该方法教 calculator 进行新操作。它需要运算符 name 和实现它的双参数函数 func(a,b)

    let powerCalc = new Calculator;
    powerCalc.addMethod("*", (a, b) => a * b);
    powerCalc.addMethod("/", (a, b) => a / b);
    powerCalc.addMethod("**", (a, b) => a ** b);
          
    let result = powerCalc.calculate("2 ** 3");
    console.log(result); // 8
    
    1
    2
    3
    4
    5
    6
    7
点击查看
  function Calculator() {
    this.methods = {
      '+': (a ,b) => a + b,
      '-': (a, b) => a - b
    }

    this.calculate = function(str) {
      let arr = str.split(' ')
      let a = +arr[0]
      let operator = arr[1]
      let b = +arr[2]

      if(!this.methods[operator] || isNaN(a) || isNaN(b)) {
        return NaN
      }

      return this.methods[operator](a, b)
    }

    this.addMethod = function(name, func) {
      this.methods[name] = func
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

关键词:对象方法 | split

# filter()

# 过滤范围

写一个函数 filterRange(arr, a, b) ,该函数获取一个数组 arr ,在其中查找数值大于或等于 a ,且小于或等于 b 的元素,并将结果以数组的形式返回。该函数不应该修改原数组。它应该返回新的数组。

相关用例:

let arr = [5, 3, 8, 1];
let filtered = filterRange(arr, 1, 4);
alert( filtered ); // 3,1(匹配值)
alert( arr ); // 5,3,8,1(未修改)
1
2
3
4
点击查看
function filterRange(arr, a, b) {
    return arr.filter((item) => item >= a && item <= b)
  }
1
2
3

# 原位过滤范围

与上一题类似,在原数组中,过滤(删除)不在 [a, b] 范围内的元素。该函数应该只修改数组。它不应该返回任何东西。

相关用例:

let arr = [5, 3, 8, 1];
filterRangeInPlace(arr, 1, 4); // 删除了范围在 1 到 4 之外的所有值
alert( arr ); // [3, 1]
1
2
3
点击查看
function filterRangeInPlace(arr, a, b) {

  for (let i = 0; i < arr.length; i++) {
    let val = arr[i];

    // 如果超出范围,则删除
    if (val < a || val > b) {
      arr.splice(i, 1);
      i--;
    }
  }

}
1
2
3
4
5
6
7
8
9
10
11
12
13

# map() 映射

# 映射到 names

user 对象数组,每个对象都有 user.name ,将其转换为 names 数组的代码。

let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 28 };

let users = [ john, pete, mary ];
let names = /* ... your code */

console.log(names); // John, Pete, Mary
1
2
3
4
5
6
7
8
点击查看
let names = users.map((user) => user.name)
1

# 映射到对象

以数组 users 为基础,创建另一个具有 idfullName 的对象数组,其中 fullNamenamesurname 生成。

let john = { name: "John", surname: "Smith", id: 1 };
let pete = { name: "Pete", surname: "Hunt", id: 2 };
let mary = { name: "Mary", surname: "Key", id: 3 };

let users = [ john, pete, mary ];

let usersMapped = /* ... your code ... */

/*
usersMapped = [
  { fullName: "John Smith", id: 1 },
  { fullName: "Pete Hunt", id: 2 },
  { fullName: "Mary Key", id: 3 }
]
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
点击查看
let usersMapped = users.map((user) => ({
  fullName: `${user.name} ${user.surname}`,
  id: user.id
}))
1
2
3
4

注意

注意,在箭头函数中,返回一个对象需要使用额外的括号。如果只写一个 {} ,JavaScript 在这里会把 { 视为函数体的开始,而不是对象的开始。解决方法是将它们包装在普通括号 () 中。

# sort() 数组排序

# 根据对象中的数据排序

编写函数 sortByAge(users) 获得对象数组的 age 属性,并根据 age 对这些对象数组进行排序。

let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 28 };

let arr = [ pete, john, mary ];

sortByAge(arr);
1
2
3
4
5
6
7
点击查看
function sortByAge(arr) {
  arr.sort((a, b) => a.age - b.age)
}
1
2
3

# 随机排序

编写函数 shuffle(array)let arr = [1, 2, 3]; 随机排序。所有元素顺序应该具有相等的概率。例如,可以将 [1,2,3] 重新排序为 [1,2,3][1,3,2][3,1,2] 等,每种情况的概率相等。

点击查看

思路:使用 Math.random() 生成一个 可能是正数或者负数的 随机数,这样 sort() 才能随机对数组中的元素重新排序。

简单的使用 Math.random() - 0.5 ,但是这个方法得出所有的排列的概率不相同。

function shuffle(array) {
  array.sort((a, b) => (Math.random() - 0.5))
}
1
2
3

能实现的一个算法「Fisher-Yates shuffle (opens new window)」,逆向遍历数组,并将每个元素与前面的随机的一个元素互换位置。能实现得出所有排列都以相同的概率出现,并且不需排序增加时间开销。

function shuffle(array) {
  for(let i = array.length - 1; i > 0; i--) {
    let j = Math.floor(Math.random() * (i + 1))
    
    // 一般交换
    let temp = array[i]
    array[i] = array[j]
    array[j] = array[i]
  }
}
1
2
3
4
5
6
7
8
9
10

使用解构分配交换:

[array[i], array[j]] = [array[j], array[i]]
1

关键字: Math.random() | sort()

# reduce()

# 计算平均值

编写 getAverageAge(users) 函数,该函数获取一个具有 age 属性的对象数组,并返回平均年龄。

let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 29 };

let arr = [ john, pete, mary ];

alert( getAverageAge(arr) );
1
2
3
4
5
6
7
点击查看
function getAverageAge(arr) {
  return arr.reduce((sum, item) => sum + item.age, 0) / arr.length
}
1
2
3

# 从数组创建对象

假设收到了一个用户数组,形式为: {id:..., name:..., age:... }

创建一个函数 groupById(arr) 从该数组创建对象,以 id 为键(key),数组项为值。

let users = [
  {id: 'john', name: "John Smith", age: 20},
  {id: 'ann', name: "Ann Smith", age: 24},
  {id: 'pete', name: "Pete Peterson", age: 31},
];

let usersById = groupById(users);

// after: 
/* 
usersById = {
  john: {id: 'john', name: "John Smith", age: 20},
  ann: {id: 'ann', name: "Ann Smith", age: 24},
  pete: {id: 'pete', name: "Pete Peterson", age: 31},
}
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
点击查看
function groupById(array) {
    return array.reduce((obj, item)=>{
      obj[item.id] = item
      return obj
    },{})
  }
1
2
3
4
5
6

注意要将累加器的初始值设置为 {}

# includes()

# 数组去重

创建一个函数 unique(arr) ,返回去除重复元素后的数组 arr

function unique(arr) {
  /* your code */
}

let strings = ["Hare", "Krishna", "Hare", "Krishna",
  "Krishna", "Krishna", "Hare", "Hare", ":-O"
];
1
2
3
4
5
6
7
点击查看
function unique(arr){
  let res = []
  
  for (let item of arr) {
    if(!res.includes(item)){
      res.push(item)
    }
  }
  return res
}
1
2
3
4
5
6
7
8
9
10
📢 上次更新: 2022/09/02, 10:18:16