刷题 | 牛客 - js中等题-下 (更ing)45/54知识点解答
非数组 转为真正的数组:① 展开运算符 [... ] 、② Array.from( )
JS45 数组去重
描述
为 Array 对象添加一个去除重复项的方法
示例1
输入:
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a', 'a', NaN]
复制输出:
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a']
法一:基础方法(仅限基础值)数组.includes()是否包含 + push + for...of
思路:设置一个数组result,遍历Array数组 即this,查看result中是否有该值 没有 则push进
Array.prototype.uniq = function () {// 法一:仅限基础值的写法:设置一个数组result,遍历Array数组 即this,查看result中是否有该值 没有 则push进const result = []for(const value of this){if(!result.includes(value)){result.push(value)}}return result;}
法二:Set 方法,支持对象引用判断(不重复同一引用)
Array.prototype.uniq = function () {// 法二:支持对象引用判断(不重复同一引用)const seen = new Set();const result = []for(const value of this){if(!seen.has(value)){seen.add(value);result.push(value);}}return result;
}
法三:Set 集合 快速去重(仅对基本类型有效)
Array.prototype.uniq = function () {// 法三:Set方法(仅对基本类型有效)return [...new Set(this)];// Set不做深比较,引用类型如[],{}每个都是唯一的// Set对象允许存储任何类型的唯一值,可以直接利用set把数组去重,但它返回的是Set类型对象,所以要在转为数组。
}
Array.prototype.uniq = function () {return Array.from(new Set(this));
}
Set 不做深比较,引用类型 如 [],{} 每个都是唯一的
Set 对象 允许存储任何类型的唯一值,可以直接利用 set 把数组去重,但它返回的是Set 类型对象,可迭代 但不是数组,所以要在转为数组。
使用 展开运算符 [... ]、Array.from( ) 将其转为真正的数组
法四:reduce(callback , initialVal 初始值) 实现数组去重
callback 的结构:( accumulator,currentValue,currentIndex,array ) => { }
( 累加器,当前元素,当前索引,数组 ) => { }
当前的累加器 是 “累积某种结果”,可以是 数组、对象、字符串、数字都可以
Array.prototype.uniq = function () {// 法四:reduce方法let result = this.reduce((pre, cur) => {if(pre.includes(cur)){return pre;}else {return pre.concat(cur);}}, [])return result;
}
Array.prototype.uniq = function () {// 法四:reduce方法let result = this.reduce((pre, cur) => {if(!pre.includes(cur)){pre.push(cur)}return pre;}, [])return result;
}
法五:Map 记录 + 数组.filter 过滤去重
Array.prototype.uniq = function () {const res = new Map();return arr.filter((a) => !res.has(a) && res.set(a, 1)) // 当不存在时,res 映射 设置 键为a 值为1
}
知识点:数据结构分类(Array、类数组arguments、Map、Set、WeakMap、WeakSet)
数据结构 | 是否类数组 | 是否可迭代 | 是否可索引访问 | 是否有 length |
---|---|---|---|---|
Array | ✅ | ✅ | ✅ | ✅ |
类数组(如 arguments ) | ✅ | ❌(旧式) | ✅ | ✅ |
Map | ❌ | ✅(for...of) | ❌ | ❌(有 .size ) |
Set | ❌ | ✅ | ❌ | ❌(有 .size ) |
WeakMap / WeakSet | ❌ | ❌ | ❌ | ❌ |
Map 映射 和 Set 集合
Map 映射(哈希映射),键值对(键和值),键可任意类型,强引用(不会被GC自动回收)—— 类似于 对象{},{key:value}
Set 集合(哈希集合),没有键 只有值,值不重复(值唯一),—— 类似于 数组[],[value]
WeekMap 弱映射,键必为对象,弱引用(无引用 则被GC垃圾回收自动收回),不可枚举
WeekSet 弱集合,值必为对象,弱引用(无引用 则被GC垃圾回收自动收回),不可枚举
Set.prototype.size 获取 Set 元素个数,判断两个集合大小是否一致。
Set.prototype.has(value) 检查 Set 是否存在指定值,时间复杂度O(1)
for...of 遍历值 (适用于 数组、Set)
for...in 遍历键(适用于 对象)
参考:
JS | 知识点总结 - Map 键值对 和 Set 集合 、WeekMap和WeekSet 等对比-CSDN博客
★JS47 时间格式化输出
描述
按所给的时间格式输出指定的时间
格式说明
对于 2014.09.05 13:14:20
yyyy: 年份,2014
yy: 年份,14
MM: 月份,补满两位,09
M: 月份, 9
dd: 日期,补满两位,05
d: 日期, 5
HH: 24制小时,补满两位,13
H: 24制小时,13
hh: 12制小时,补满两位,01
h: 12制小时,1
mm: 分钟,补满两位,14
m: 分钟,14
ss: 秒,补满两位,20
s: 秒,20
w: 星期,为 ['日', '一', '二', '三', '四', '五', '六'] 中的某一个,本 demo 结果为 五
输入描述:
formatDate(new Date(1409894060000), 'yyyy-MM-dd HH:mm:ss 星期w')
输出描述:
2014-09-05 13:14:20 星期五
示例1
输入:
formatDate(new Date(1409894060000), 'yyyy-MM-dd HH:mm:ss 星期w')
输出:
2014-09-05 13:14:20 星期五
法一:封装一个函数补 0 + 普通对象 放键值对{ 'key': value } + 改格式使用 规定格式.replace(key, 对象[key])
function formatDate(date, format) {let addZero = function(data){if(data < 10){return '0' + data}return data;}let obj = {// 获取年月日'yyyy': date.getFullYear(),'yy': date.getFullYear() % 100,'MM': addZero(date.getMonth() + 1),'M': date.getMonth() + 1,'dd': addZero(date.getDay()),'d': date.getDay(),// 获取时分秒'HH': addZero(date.getHours()),'H': date.getHours(),'hh': addZero(date.getDay() % 12 || 12),'h': date.getDay() % 12 || 12,'mm': addZero(date.getMinutes()),'m': date.getMinutes(),'ss': addZero(date.getSeconds()),'s': date.getSeconds(),'w': ['日', '一', '二', '三', '四', '五', '六'][date.getDay()]}for(let i in obj){format = format.replace(i, obj[i]);}return format;}
str.padStart(字符串长度, 要用来补全的字符串) 字符串的方法,用于在字符串前面补全指定字符,直到达到指定的长度。
例子:
'5'.padStart(2, '0') // '05' '12'.padStart(2, '0') // '12' '1'.padStart(3, '0') // '001' 'abc'.padStart(6, '-') // '---abc'