猿问

Javascript 中高效的人类可读日期字符串排序算法

我正在尝试从我的 React 表中的数据库中对数千个日期字符串进行排序。我正在使用的组件允许用户通过单击最上面的行来对信息进行排序,API 在这里。


我最初对排序函数进行了编程,以检查输入排序的字符串是否有效,moment.js如果有效,则获取该日期字符串的总毫秒值,从数组中的后续值中减去它,然后然后返回结果。


然而,事实证明这个过程是劳动密集型的,并且导致排序功能在浏览器上运行时滞后。相关的代码如下所示:


let isValidDate = (date) => moment(date,'MMM D, YYYY hh:mm a', true).isValid();


function sort(a, b) { // Sorting algorithm 

    if(isValidDate(a) && isValidDate(b)){

      return 

      if(moment(b).valueOf() < moment(a).valueOf()){

        return -1;

      }

      if(moment(b).valueOf() > moment(a).valueOf()){

        return 1;

      }

    }

    return 0;

  }

由于我的表格显示日期的方式(作为人类可读的字符串),我需要一些方法来更有效地按时间对字符串进行排序。有没有人对如何实现这一目标有任何建议?我正在对数千个值进行排序,而这个解决方案又太慢了。


撒科打诨
浏览 236回答 2
2回答

万千封印

我假设这些字符串是您的状态数据的一部分。而不是仅仅存储字符串(如果这就是你正在做的事情),我会将带有日期值的对象分别存储为数字(自大纪元以来的毫秒数)和人类可读的字符串。然后排序回调可以直接使用数字,而不必不断地重新解析字符串。现场示例:class Example extends React.Component {&nbsp; &nbsp; constructor(props) {&nbsp; &nbsp; &nbsp; &nbsp; super(props);&nbsp; &nbsp; &nbsp; &nbsp; this.state = {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; list: props.list.map(strValue => ({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dateValue: moment(strValue, 'MMM D, YYYY hh:mm a').valueOf() || 0, // `|| 0` because `valueOf` will return NaN if the date is invalid; we substitute 0 instead&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strValue&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }))&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; this.sortAscending&nbsp; = this.sortAscending.bind(this);&nbsp; &nbsp; &nbsp; &nbsp; this.sortDescending = this.sortDescending.bind(this);&nbsp; &nbsp; }&nbsp; &nbsp; sortAscending() {&nbsp; &nbsp; &nbsp; &nbsp; this.setState(({list}) => ({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; list: list.slice().sort((a, b) => a.dateValue - b.dateValue)&nbsp; &nbsp; &nbsp; &nbsp; }));&nbsp; &nbsp; }&nbsp; &nbsp; sortDescending() {&nbsp; &nbsp; &nbsp; &nbsp; this.setState(({list}) => ({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; list: list.slice().sort((a, b) => b.dateValue - a.dateValue)&nbsp; &nbsp; &nbsp; &nbsp; }));&nbsp; &nbsp; }&nbsp; &nbsp; render() {&nbsp; &nbsp; &nbsp; &nbsp; const {list} = this.state;&nbsp; &nbsp; &nbsp; &nbsp; return (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <React.Fragment>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <input type="button" onClick={this.sortAscending} value="Sort Ascending" />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <input type="button" onClick={this.sortDescending} value="Sort Descending" />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <table>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <tbody>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {list.map(({strValue}, index) => (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <tr key={index}>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <td>{strValue}</td>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </tr>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ))}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </tbody>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </table>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </React.Fragment>&nbsp; &nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; }}const list = [&nbsp; &nbsp; "Jan 2, 2017 12:55 am",&nbsp; &nbsp; "Nov 17, 2012 09:06 am",&nbsp; &nbsp; "May 19, 2015 05:20 am",&nbsp; &nbsp; "May 3, 2015 12:30 pm",&nbsp; &nbsp; "Nov 13, 2011 01:44 pm",&nbsp; &nbsp; "Jun 25, 2012 03:23 am",&nbsp; &nbsp; "Dec 12, 2017 07:42 pm",&nbsp; &nbsp; "Dec 12, 2011 04:51 am",&nbsp; &nbsp; "Oct 31, 2016 05:56 am",&nbsp; &nbsp; "Jan 11, 2013 12:17 pm",&nbsp; &nbsp; "Jun 20, 2018 07:05 pm",&nbsp; &nbsp; "Mar 21, 2013 04:23 am",&nbsp; &nbsp; "Oct 8, 2010 06:37 pm",&nbsp; &nbsp; "Jun 23, 2011 04:00 am",&nbsp; &nbsp; "Feb 16, 2016 08:57 am",&nbsp; &nbsp; "Jul 10, 2016 10:03 pm",&nbsp; &nbsp; "Nov 16, 2015 12:17 pm",&nbsp; &nbsp; "Jul 7, 2013 05:53 am",&nbsp; &nbsp; "Oct 11, 2016 11:52 pm",&nbsp; &nbsp; "May 20, 2015 01:00 pm",&nbsp; &nbsp; "Oct 4, 2016 10:06 am",&nbsp; &nbsp; "Aug 27, 2015 06:16 am",&nbsp; &nbsp; "Feb 24, 2013 07:39 am",&nbsp; &nbsp; "Jul 28, 2018 10:06 pm",&nbsp; &nbsp; "Nov 2, 2018 03:24 am",&nbsp; &nbsp; "Apr 23, 2016 09:36 pm",&nbsp; &nbsp; "Apr 11, 2010 05:21 am",&nbsp; &nbsp; "May 16, 2014 07:52 pm",&nbsp; &nbsp; "Sep 17, 2011 05:25 pm",&nbsp; &nbsp; "Sep 25, 2010 11:55 am",&nbsp; &nbsp; "Jan 30, 2016 01:43 am",&nbsp; &nbsp; "Sep 20, 2017 08:23 pm",&nbsp; &nbsp; "Feb 6, 2010 01:41 pm",&nbsp; &nbsp; "Jul 1, 2009 07:05 am",&nbsp; &nbsp; "Jul 12, 2013 03:42 pm",&nbsp; &nbsp; "Jun 21, 2011 02:57 am",&nbsp; &nbsp; "Jan 16, 2015 05:55 pm",&nbsp; &nbsp; "Mar 11, 2012 05:19 pm",&nbsp; &nbsp; "Dec 22, 2013 06:34 pm",&nbsp; &nbsp; "Oct 29, 2012 07:20 am",&nbsp; &nbsp; "May 26, 2015 04:00 am",&nbsp; &nbsp; "Feb 21, 2017 09:34 am",&nbsp; &nbsp; "Mar 31, 2015 03:37 pm",&nbsp; &nbsp; "Jan 24, 2011 11:31 pm",&nbsp; &nbsp; "May 28, 2017 03:45 am",&nbsp; &nbsp; "Jan 19, 2010 06:45 pm",&nbsp; &nbsp; "Jul 31, 2016 03:29 am",&nbsp; &nbsp; "May 27, 2011 12:12 am",&nbsp; &nbsp; "Dec 7, 2014 11:27 pm",&nbsp; &nbsp; "Oct 10, 2016 02:48 am"];ReactDOM.render(&nbsp; &nbsp; <Example list={list} />,&nbsp; &nbsp; document.getElementById("root"));<div id="root"></div><script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

跃然一笑

正如他所建议的,我最终改变了我的后端,只将日期作为数字返回。但是,如果我没有这样做,我发现的另一个更快的解决方案是这种排序函数,它利用了当 moment.js 无法解析字符串时返回 NaN 的事实:let date1 = moment(a[orderBy]).valueOf();let date2 = moment(b[orderBy]).valueOf();&nbsp; &nbsp; if(isNaN(date1) || isNaN(date2)){&nbsp; &nbsp; &nbsp; return 0;&nbsp; &nbsp; }&nbsp; &nbsp; if(date2 < date1){&nbsp; &nbsp; &nbsp; return -1;&nbsp; &nbsp; }&nbsp; &nbsp; if(date2 > date1){&nbsp; &nbsp; &nbsp; return 1;&nbsp; &nbsp; }&nbsp; };
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答