1. 通过键对对象数组进行分组
我们定义了一个名为 groupBy 的函数,它以一个对象数组和一个键作为参数。该函数的目的是将数组中的对象按指定的键进行分组。
const groupBy = (arr, key) =>
arr.reduce(
(acc, obj) => ({ ...acc, [obj[key]]: [...(acc[obj[key]] || []), obj] }),
{}
)
const people = [
{ name: "Alice", age: 21 },
{ name: "Bob", age: 22 },
{ name: "Charlie", age: 21 },
{ name: "David", age: 23 },
{ name: "Eve", age: 22 }
]
console.log(groupBy(people, "age"))
/* Output:
{
21: [
{ name: "Alice", age: 21 },
{ name: "Charlie", age: 21 }
],
22: [
{ name: "Bob", age: 22 },
{ name: "Eve", age: 22 }
],
23: [{ name: "David", age: 23 }]
}
*/
acc 参数是累加分组对象的累加器。obj 参数表示数组中的每个对象。
在 reduce() 方法内部,使用扩展运算符 (...acc) 返回一个新对象。这将创建 accumulator 对象的浅表副本,以便可以在不更改原始对象的情况下对其进行修改。
新对象的属性设置为与 key 参数的值相匹配的键。该属性的值是一个包含被迭代对象的数组。
(acc[obj[key]] || []) 表达式检查该属性是否存在于累加器对象中。如果不存在,则返回一个空数组。展开运算符用于将数组与正在迭代的当前对象连接起来。
最后,groupBy() 函数返回包含分组对象的累加器对象。
2. 返回数组的中位数
我们实现了一个名为 median 的函数,它将一个数字数组作为输入,按升序对其进行排序,并返回排序后的数组的中值。
当数组的元素个数为奇数时,排序数组的中值就是中间的元素。当数组元素个数为偶数时,中值取中间两个元素的平均值。
const median = (arr) => {
const sorted = arr.sort()
const middle = Math.floor(sorted.length / 2)
return sorted.length % 2 === 0
? (sorted[middle - 1] + sorted[middle]) / 2
: sorted[middle]
}
const oddArr = [3, 1, 4, 2, 5]
console.log(median(oddArr)) // 3
const evenArr = [1, 2, 5, 6]
console.log(median(evenArr)) // 3.5
第一个例子,输入数组[3, 1, 4, 2, 5]被排序为[1, 2, 3, 4, 5],中间元素为3。因此,输入数组的中值 是 3。
在第二个例子中,输入数组[1,2,5,6]被排序为[1,2,5,6],中间两个元素为2和5。因此,输入数组的中值为 (2 + 5) / 2 = 3.5。
3.返回数组的模式
数组的众数是数组中出现频率最高的值。如果有多个值具有相同的最高频率,则所有这些值都被视为众数。
const mode = (arr) => {
const counts = arr.reduce(
(acc, curr) => ({ ...acc, [curr]: (acc[curr] || 0) + 1 }),
{}
)
const maxCount = Math.max(...Object.values(counts))
return Object.keys(counts)
.filter((key) => counts[key] === maxCount)
.map(Number)
}
const arr1 = [1, 2, 3, 2, 4, 2, 5]
console.log(mode(arr1)) // [2]
const arr2 = [1, 2, 3, 2, 4, 4, 5]
console.log(mode(arr2)) // [2, 4]
在第一个示例中,输入数组 [1, 2, 3, 2, 4, 2, 5] 的计数为 { 1: 1, 2: 3, 3: 1, 4: 1, 5: 1 }。最高计数为 3,出现值 2。因此,输入数组的模式为 [2]。
在第二个示例中,输入数组 [1, 2, 3, 2, 4, 4, 5] 的计数为 { 1: 1, 2: 2, 3: 1, 4: 2, 5: 1 }。最高计数为 2,出现在值 2 和 4 中。因此,输入数组的模式为 [2, 4]。
4. 使用扩展运算符和 Array.from 创建一个长度为 n 的数组
使用扩展运算符和 Array.from() 创建一个长度为 n 的新数组。生成的数组包含从 0 到 n-1 的升序排列的数字。
const n = 5
const arr = [...Array.from({ length: n }, (_, index) => index)]
console.log(arr) // [ 0, 1, 2, 3, 4 ]
在此示例中,n 设置为 5,因此,生成的数组 arr 的长度为 5。数组的值是使用函数 (_, index) => index 生成的,该函数返回数组的当前索引。因此,结果数组将为 [0, 1, 2, 3, 4]。
5. 使用解构获取数组的最后一个元素
此函数的目的是使用解构获取数组的最后一个元素。
const last = (arr) => [...arr].pop()
const people = [
{ name: "Alice", age: 21 },
{ name: "Bob", age: 22 },
{ name: "Charlie", age: 21 },
{ name: "David", age: 23 },
{ name: "Eve", age: 22 }
]
console.log(last(people)) // { name: "Eve", age: 22 }
在 last() 函数内部,展开运算符 (...) 用于创建原始数组的副本。这是必需的,因为 pop() 方法会修改原始数组并返回删除的元素。
然后,对数组的副本调用 pop() 方法,删除并返回数组的最后一个元素。由于在调用 pop() 方法之前复制了数组,因此不会修改原始数组。
last() 函数返回数组的最后一个元素。
6. 使用布尔构造函数检查变量是否为真
我们函数的目的是使用布尔构造函数检查变量是否为真。
布尔构造函数是 JavaScript 中的一个内置函数,可将值转换为布尔值。如果该值为 truthy,则布尔构造函数返回 true。如果该值为 falsy,则布尔构造函数返回 false。
const isTruthy = (val) => Boolean(val)
console.log(isTruthy(false)) // false
console.log(isTruthy(0)) // false
console.log(isTruthy(-0)) // false
console.log(isTruthy(0n)) // false
console.log(isTruthy("")) // false
console.log(isTruthy(null)) // false
console.log(isTruthy(undefined)) // false
console.log(isTruthy(NaN)) // false
console.log(isTruthy(true)) // true
console.log(isTruthy({})) // true
console.log(isTruthy([])) // true
console.log(isTruthy(42)) // true
console.log(isTruthy("0")) // true
console.log(isTruthy("false")) // true
console.log(isTruthy(new Date())) // true
console.log(isTruthy(Infinity)) // true
7. 从数组中删除虚假值
布尔构造函数用作 filter() 方法的回调函数。如果值为真,则布尔构造函数返回真,如果值为假,则返回假。因此,filter() 方法从原始数组中删除所有虚假值。
const compact = (arr) => arr.filter(Boolean)
const falsyArr = [false, 0, -0, 0n, "", null, undefined, NaN]
const mixArr = [true, false, {}, 0, [], "", "0", null, "false", undefined, 42]
console.log(compact(falsyArr)) // []
console.log(compact(mixArr)) // [ true, {}, [], '0', 'false', 42 ]
在 compact() 函数内部,使用布尔构造函数作为回调函数对 arr 参数调用 filter() 方法。这将返回一个新数组,其中仅包含原始数组的真值。
compact() 函数返回新数组。
当执行 console.log() 语句时,compact(falsyArr) 的输出是一个空数组,因为 falsyArr 数组中的所有值都是假的。compact(mixArr) 的输出是一个数组,它只包含 mixArr 数组的真实值,即 true、一个空对象 {}、一个空数组 []、字符串“0”、字符串“false”,以及 数字 42。所有虚假值(false、0、""、null、undefined 和 NaN)都已从 mixArr 数组中删除。
8. 将字符串数组转换为数字
函数的目的是将字符串数组转换为数字数组。Number 构造函数用作 map() 方法的回调函数。Number 构造函数将字符串转换为数字。
const toNumbers = (arr) => arr.map(Number)
const strArr = ["1", "2", "3", "4", "5"]
console.log(toNumbers(strArr)) // [ 1, 2, 3, 4, 5 ]
在 toNumbers() 函数内部,使用 Number 构造函数作为回调函数对 arr 参数调用 map() 方法。这将返回一个包含转换值的新数组。
9. 返回一个键值翻转的对象
此函数的目的是返回一个新对象,其中翻转了原始对象的键和值。
Object.entries() 方法用于从原始对象创建键值对数组。然后使用 map() 方法迭代数组中的每个键值对,并返回一个新的翻转键值对数组。最后,使用 Object.fromEntries() 方法从翻转的键值对数组中创建一个新对象。
const flip = (obj) =>
Object.fromEntries(Object.entries(obj).map(([key, value]) => [value, key]))
const myDog = {
firstName: "oscar",
lastName: "king",
age: 3
}
console.log(flip(myDog)) // { 3: 'age', oscar: 'firstName', king: 'lastName' }
在 flip() 函数内部,对 obj 参数调用 Object.entries() 方法以创建键值对数组。然后,在键值对数组上调用 map() 方法。对于每个键值对,map() 方法解构键和值变量,并返回一个新数组,其中值作为第一个元素,键作为第二个元素。这将创建一个翻转的键值对数组。
最后,在翻转的键值对数组上调用 Object.fromEntries() 方法以使用翻转的键值对创建一个新对象。
flip() 函数返回新对象。
执行 console.log() 语句时,输出是一个新对象,其中翻转了原始 myDog 对象的键和值。firstName 键及其值“oscar”已翻转为“oscar”键及其值“firstName”。lastName 键及其值“king”已翻转为“king”键及其值“lastName”。age 键及其值 3 已翻转为 3 键及其值“age”。
10. 返回一个只有特定键的对象
此函数的目的是返回一个新对象,该对象仅包含原始对象中指定的键及其对应的值。
const pick = (obj, keys) =>
Object.fromEntries(
Object.entries(obj).filter(([key]) => keys.includes(key))
)
const myDog = {
firstName: "oscar",
lastName: "king",
age: 3
}
console.log(pick(myDog, [])) // {}
console.log(pick(myDog, ["firstName"])) // { firstName: 'oscar' }
console.log(pick(myDog, ["firstName", "lastName"])) // { firstName: 'oscar', lastName: 'king' }
在 pick() 函数内部,对 obj 参数调用 Object.entries() 方法以创建键值对数组。然后,在键值对数组上调用 filter() 方法。对于每个键值对,filter() 方法解构键变量,如果键数组包含键则返回 true。这将创建一个过滤后的键值对数组。
最后,在过滤后的键值对数组上调用 Object.fromEntries() 方法来创建一个仅包含指定键及其对应值的新对象。pick() 函数返回新对象。
11. 返回一个只有唯一值的对象
此函数 uniqueValues 将一个对象作为参数并返回一个新对象,该对象仅包含来自输入对象的唯一值。
const uniqueValues = (obj) =>
Object.fromEntries(
Object.entries(obj).filter(
([key, value], index, entries) =>
entries.findIndex(([k, v]) => v === value) === index
)
)
const myDog = {
id: 3,
firstName: "oscar",
lastName: "oscar",
age: 3
}
console.log(uniqueValues(myDog)) // { id: 3, firstName: 'oscar' }
它首先在输入对象上调用 Object.entries() 方法以获取键值对数组。然后,它使用 filter() 方法过滤条目数组,并仅返回值唯一的条目。
要检查一个值是否唯一,它在原始条目数组上使用 findIndex() 方法。它查找与当前过滤的条目具有相同值的第一个条目的索引。如果当前条目的索引等于第一个匹配条目的索引,则意味着该值是唯一的,应该包含在结果对象中。
最后,它使用 Object.fromEntries() 方法将过滤后的条目数组转换回对象。
在示例代码中,使用具有某些重复值的对象 myDog 调用 uniqueValues 函数。该函数返回一个仅包含唯一值并删除重复值的新对象。生成的对象具有 id:3 和 firstName:'oscar'。