为何基于时间字段的JavaScript数组无法按升序正确排序?
排序失效原因
你的代码排序不生效的核心问题非常明确:Array.sort()的比较回调必须返回数字类型结果:返回值小于0时a排在b之前,大于0时b排在a之前,等于0时两者相对位置不变。但你的代码里对moment实例调用.format('hh:mm a')得到的是字符串类型值,两个字符串直接做算术减法的结果永远是NaN,sort回调返回NaN时排序逻辑完全不可预期,自然得不到正确的升序结果。
你搜到的同类用format返回值做减法的实现本身就是错误用法,完全违背了moment和Array.sort的API设计规则。
修复方案
基于moment的正确写法
比较moment时间直接取时间戳做数字差值即可,不需要做格式化操作。解析12小时制时间时建议显式传入格式字符串,避免解析歧义:
let myVar = [{time: "3:00 pm", name: "Landon"},{time: "5:20 pm", name: "Amanda"},{time: "4:00 pm", name: "Kid"}] const sortedArray = myVar.sort((a,b) => { // 显式指定解析格式,通过valueOf拿到毫秒级时间戳做数字比较 return moment(a.time, 'hh:mm a').valueOf() - moment(b.time, 'hh:mm a').valueOf() }) console.log(sortedArray)
无依赖原生JS写法
如果不想引入moment库,也可以手动把12小时制时间转为当日累计分钟数做比较,逻辑轻量且无兼容问题:
const sortedArray = myVar.sort((a, b) => { const timeToMinutes = (timeStr) => { const [clock, period] = timeStr.split(' ') let [hour, minute] = clock.split(':').map(Number) // 12小时制转24小时制 if (period.toLowerCase() === 'pm' && hour !== 12) hour += 12 if (period.toLowerCase() === 'am' && hour === 12) hour = 0 return hour * 60 + minute } return timeToMinutes(a.time) - timeToMinutes(b.time) })
两种写法运行后都会得到正确的升序结果:3:00 pm(Landon)→ 4:00 pm(Kid)→ 5:20 pm(Amanda)
内容的提问来源于stack exchange,提问作者WeAreHawk09
相关产品推荐
相关产品推荐

