JavaScript获取指定范围内对象数据:修复错误及ES6实现
如何从对象数组中筛选timestamp在指定范围内的数据?
嘿,我看你在写时间范围筛选函数的时候遇到了几个问题,咱们来一步步拆解问题,然后给出可行的解决方案:
你的当前函数存在的核心问题
咱们先看看你写的getValuesInRange函数为什么会报错,以及逻辑上的漏洞:
indexOf is not defined错误:indexOf是数组的原型方法,你直接全局调用indexOf(from)肯定会报错——你既没有指定要在哪个数组里查找,甚至连要处理的原始data数组都没传入函数里。- 空数组
sortedArray:你初始化了sortedArray但完全没有把原始数据赋值给它,后续的循环根本没有任何数据可以处理,等于白跑。 - 字段不匹配:你的数据对象里用的是
timestamp字段,但代码里却写了valueAtIndex.key和valueAtIndex.value,这完全对应不上;而且从你的需求来看,你应该是要保留整个对象或者里面的字段,而不是什么key/value结构。 - 逻辑缺失:函数既没有对原始数据做排序(虽然你的示例数据是有序的,但通用场景下必须考虑无序的情况),也没有正确关联输入的
from/to和数据的timestamp字段。
正确的实现思路
幸运的是,你的timestamp是ISO 8601格式的字符串,这种字符串可以直接按字典序比较(因为它的时间单位是从年到秒依次排列的),所以不需要转成Date对象也能直接比较大小;当然,转成Date对象的时间戳来比较也是完全可行的,两种方式都没问题。
修复后的基础版函数
首先,我们把data数组传入函数,修正字段和逻辑:
function getValuesInRange(data, from, to) { // 先复制数组并按timestamp排序(处理原始数据无序的情况) const sortedArray = [...data].sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp)); const filteredValues = []; // 找到第一个timestamp >= from的元素索引 let index = sortedArray.findIndex(item => item.timestamp >= from); // 如果没有符合条件的元素,直接返回空数组 if (index === -1) return filteredValues; while (index < sortedArray.length) { const currentItem = sortedArray[index]; // 检查是否在[from, to)的左闭右开区间内 if (currentItem.timestamp < to) { filteredValues.push(currentItem); // 若只需提取某个字段,比如temperature,改为currentItem.temperature即可 index++; } else { break; } } return filteredValues; } // 测试用例 const data = [ { timestamp: '2015-09-01T16:00:00.000Z', temperature: 27.1, dewPoint: 17.1 }, { timestamp: '2015-09-01T16:10:00.000Z', temperature: 27.2, dewPoint: 17.2 }, { timestamp: '2015-09-01T16:20:00.000Z', temperature: 27.3, dewPoint: 17.3 }, { timestamp: '2015-09-01T16:30:00.000Z', temperature: 27.4, dewPoint: 17.4 } ]; const fromDateTime = data[0].timestamp; const toDateTime = data[2].timestamp; console.log(getValuesInRange(data, fromDateTime, toDateTime)); // 输出:[{timestamp: '2015-09-01T16:00:00.000Z', ...}, {timestamp: '2015-09-01T16:10:00.000Z', ...}]
ES6 简洁等价实现
利用数组的filter方法,结合ISO字符串的直接比较,代码会非常简洁:
const getValuesInRangeES6 = (data, from, to) => // 若原始数据已按timestamp升序排列,可去掉sort步骤优化性能 [...data] .sort((a, b) => a.timestamp.localeCompare(b.timestamp)) // 用localeCompare也能正确比较ISO字符串 .filter(item => item.timestamp >= from && item.timestamp < to); // 测试调用 console.log(getValuesInRangeES6(data, fromDateTime, toDateTime)); // 输出结果和上面一致
如果你的原始数据确定已经是按timestamp升序排列的,那么可以直接去掉sort步骤,进一步提升性能:
const getValuesInRangeES6Optimized = (data, from, to) => data.filter(item => item.timestamp >= from && item.timestamp < to);
额外说明
- 如果你需要的是闭区间(包含
to对应的时间),只需要把条件改成item.timestamp <= to即可。 - 如果你的
timestamp不是ISO格式,那必须转成Date对象的时间戳来比较,比如new Date(item.timestamp).getTime()。
内容的提问来源于stack exchange,提问作者Null isTrue
相关产品推荐
相关产品推荐

