【问题标题】:Sort an array of objects based on times string values?根据时间字符串值对对象数组进行排序?
【发布时间】:2018-01-30 10:02:19
【问题描述】:

我有一个对象数组

var data =[
  {
    "avail": "3 Bookings Available" 
    "time": "05:00 PM to 06:00 PM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "09:00 AM to 10:00 AM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "04:00 PM to 05:00 PM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "03:00 PM to 04:00 PM",
    "date": "2018-01-30"
  }];

我想按时间字符串值对数据进行排序,这样需要的输出如下所示:

 [{
    "avail": "3 Bookings Available" 
    "time": "09:00 AM to 10:00 AM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "03:00 PM to 04:00 PM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "04:00 PM to 05:00 PM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "05:00 PM to 06:00 PM",
    "date": "2018-01-30"
  }]

我已经使用了 String #localeCompare 的排序函数,但我仍然没有得到所需的输出

data.sort(function(a,b){
  return a.time.localeCompare(b.time);
});
console.log(data);

即使我使用了String#slice() 方法,通过该方法我可以使用 '1970/01/01' 作为任意日期来生成有效的日期字符串,但我仍然可以得到所需的输出任何人都可以给我以这种方式获得输出的方式提前谢谢。

data.sort(function(a, b) {
  return Date.parse('1970/01/01 ' + a.time.slice(0, -2) + ' ' + a.time.slice(-2)) - Date.parse('1970/01/01 ' + b.time.slice(0, -2) + ' ' + b.time.slice(-2))
});

例子:

var data = [{
    "avail": "3 Bookings Available",
    "time": "05:00 PM to 06:00 PM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "09:00 AM to 10:00 AM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "04:00 PM to 05:00 PM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "03:00 PM to 04:00 PM",
    "date": "2018-01-30"
  }
];

data.sort(function(a, b) {
  return Date.parse('1970/01/01 ' + a.time.slice(0, -2) + ' ' + a.time.slice(-2)) - Date.parse('1970/01/01 ' + b.time.slice(0, -2) + ' ' + b.time.slice(-2))
});
console.log(data)

【问题讨论】:

  • 我认为您无法控制服务器响应?如果你这样做了,你可以发回 ISO8601 格式,该格式可用于轻松构造Date with a dateString,即new Date("2018-01-30T12:34:56")

标签: javascript arrays string sorting time


【解决方案1】:

我有一个函数可以将这些时间变成从午夜开始的几分钟,大致类似于:

function parseTime(time) {
  var parts = time.match(/^(\d{2}):(\d{2}) (AM|PM)/i);
  if (!parts) {
    return NaN;
  }
  var adjust = parts[3].toUpperCase() == "PM" ? 12 : 0;
  return (parseInt(parts[1], 10) + adjust) * 60 + parseInt(parts[2], 10);
}

那么排序就很简单了:

data.sort(function(a, b) {
  return parseTime(a.time) - parseTime(b.time);
});

例子:

var data =[
  {
    "avail": "3 Bookings Available",
    "time": "05:00 PM to 06:00 PM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "09:00 AM to 10:00 AM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "04:00 PM to 05:00 PM",
    "date": "2018-01-30"
  },
  {
    "avail": "3 Bookings Available",
    "time": "03:00 PM to 04:00 PM",
    "date": "2018-01-30"
  }];
function parseTime(time) {
  var parts = time.match(/^(\d{2}):(\d{2}) (AM|PM)/i);
  if (!parts) {
    return NaN;
  }
  var adjust = parts[3].toUpperCase() == "PM" ? 12 : 0;
  return (parseInt(parts[1], 10) + adjust) * 60 + parseInt(parts[2], 10);
}
data.sort(function(a, b) {
  return parseTime(a.time) - parseTime(b.time);
});
console.log(data);
.as-console-wrapper {
  max-height: 100% !important;
}

经典的分治法(例如,将问题分解成更小的部分)。

【讨论】:

    【解决方案2】:

    这有效(在添加缺少的逗号之后):

    var data = [{
        "avail": "3 Bookings Available",
        "time": "05:00 PM to 06:00 PM",
        "date": "2018-01-30"
      },
      {
        "avail": "3 Bookings Available",
        "time": "09:00 AM to 10:00 AM",
        "date": "2018-01-30"
      },
      {
        "avail": "3 Bookings Available",
        "time": "04:00 PM to 05:00 PM",
        "date": "2018-01-30"
      },
      {
        "avail": "3 Bookings Available",
        "time": "03:00 PM to 04:00 PM",
        "date": "2018-01-30"
      }
    ];
    
    data.sort(function(a, b) {
      const [afrom, ato]=a.time.split(" to ");
      const [bfrom, bto]=b.time.split(" to ");
      return Date.parse(a.date + " " + afrom) - Date.parse(b.date + " "+  bfrom);  
    });
    console.log(data)

    【讨论】:

      【解决方案3】:

      普通的字符串比较就可以了,但是你需要在时间字符串的开头重新排列AMPM(使用String#replace方法)。

      var data = [{  "avail": "3 Bookings Available", "time": "05:00 PM to 06:00 PM",  "date": "2018-01-30"}, {  "avail": "3 Bookings Available",  "time": "09:00 AM to 10:00 AM",  "date": "2018-01-30"}, {  "avail": "3 Bookings Available",  "time": "04:00 PM to 05:00 PM",  "date": "2018-01-30"}, {  "avail": "3 Bookings Available",  "time": "03:00 PM to 04:00 PM",  "date": "2018-01-30"}];
      
      data.sort(function(a, b) {
        // compare the date string
        return a.date.localeCompare(b.date) ||
          // in case they are equal then compare time string
          // after converting the format
          timeFormat(a).localeCompare(timeFormat(b))
      });
      
      // function for formating the time string
      function timeFormat(o) {
        // reposition the AM or PM at the beginning of time
        // for string comparison
        return o.time.replace(/(\d{2}:\d{2}\s)(AM|PM)/g, '$2$1');
      }
      
      console.log(data);

      【讨论】:

        【解决方案4】:

        您可以合并日期和时间并创建一个日期对象,您可以在其中获取自 1970 年以来的时间(以毫秒为单位),比较这些数字并相应地对您的数组进行排序。

        【讨论】:

          【解决方案5】:

          使用辅助函数 toMilitary,您可以将时间更改为 0 到 2359 之间的数字。然后将原始数据映射到军事时间和索引。然后按军事时间排序。最后使用排序集的索引从原始数据中挑选项目来减少结果。

          以下代码不会改变任何原始数据。

              const data =[
                {
                  "avail": "3 Bookings Available",
                  "time": "05:00 PM to 06:00 PM",
                  "date": "2018-01-30"
                },
                {
                  "avail": "3 Bookings Available",
                  "time": "09:00 AM to 10:00 AM",
                  "date": "2018-01-30"
                },
                {
                  "avail": "3 Bookings Available",
                  "time": "04:00 PM to 05:00 PM",
                  "date": "2018-01-30"
                },
                {
                  "avail": "3 Bookings Available",
                  "time": "03:00 PM to 04:00 PM",
                  "date": "2018-01-30"
                }
              ];
          
              const toMilitary = timeString => {
                const time = timeString.slice(0,8);
                const amPm = time.slice(-2).toLowerCase();
                const timeNumber = parseInt(time.replace(/[^0-9]/g,""),10);
                return (amPm==="pm")?timeNumber+1200:timeNumber;
              };
          
              const sortedData = data
              .map((d,index)=>[
                toMilitary(d.time), index
              ])
              .sort((a,b)=>a[0]-b[0])
              .reduce(
                (all,[_,index])=>
                  all.concat([data[index]]),
                []
              );
              console.log(JSON.stringify(sortedData,undefined,2))

          我喜欢mplungjan 方式,它包括日期。它会在排序时多次调用解析日期和时间函数,所以我已经实现了它而不是以前的军事。首先计算所有对象的完整日期和时间并与索引配对,然后排序,然后使用排序结果的索引从数据中挑选项目:

          const data =[
            {
              "avail": "3 Bookings Available",
              "time": "05:00 PM to 06:00 PM",
              "date": "2018-01-30"
            },
            {
              "avail": "3 Bookings Available",
              "time": "09:00 AM to 10:00 AM",
              "date": "2018-01-30"
            },
            {
              "avail": "3 Bookings Available",
              "time": "04:00 PM to 05:00 PM",
              "date": "2018-01-30"
            },
            {
              "avail": "3 Bookings Available",
              "time": "03:00 PM to 04:00 PM",
              "date": "2018-01-30"
            }
          ];
          
          const fullDate = item => {
            const [from, to]=item.time.split(" to ");
            return Date.parse(item.date + " " + from);
          };
          
          const sortedData = data
          .map((d,index)=>[
            fullDate(d),index
          ])
          .sort((a,b)=>a[0]-b[0])
          .reduce(
            (all,[_,index])=>
              all.concat([data[index]]),
            []
          );
          console.log(JSON.stringify(sortedData,undefined,2))

          【讨论】:

            【解决方案6】:

            这是一个使用moment.js 解析custom format 的简单示例:

            var data = [
              { "time": "05:00 PM to 06:00 PM", "date": "2018-01-30" },
              { "time": "09:00 AM to 10:00 AM", "date": "2018-01-30" },
              { "time": "04:00 PM to 05:00 PM", "date": "2018-01-30" },
              { "time": "03:00 PM to 04:00 PM", "date": "2018-01-30" }
            ];
            
            data.sort(function(a, b) {
              let format = "YYYY-MM-DD hh:mm A";
              let ma = moment(a.date + " " + a.time, [format])
              let mb = moment(b.date + " " + b.time, [format])
              return ma.diff(mb);
            });
            
            console.log(data);
            <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>

            这是另一个示例,其中还包括排序中的结束时间(如果两个开始日期/时间相等):

            var data = [
              { "time": "09:00 PM to 06:00 PM", "date": "2018-01-30" },
              { "time": "09:00 PM to 10:00 AM", "date": "2018-01-30" },
              { "time": "09:00 PM to 05:00 PM", "date": "2018-01-30" },
              { "time": "09:00 PM to 04:00 PM", "date": "2018-01-30" }
            ];
            
            data.sort(function(a, b) {
              let format = "YYYY-MM-DD hh:mm A";
              let ma = moment(a.date + " " + a.time, [format])
              let mb = moment(b.date + " " + b.time, [format])
              let diff = ma.diff(mb);
              if(diff === 0) {
                ma = moment(a.date + " " + a.time.substring(12), [format])
                mb = moment(b.date + " " + b.time.substring(12), [format])
                diff = ma.diff(mb);
              }
            
              return diff;
            });
            
            console.log(data);
            <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-09-23
              • 1970-01-01
              • 2016-10-08
              • 1970-01-01
              • 2013-11-25
              • 2016-10-24
              • 1970-01-01
              • 2021-10-30
              相关资源
              最近更新 更多