简体   繁体   English

根据时间字符串值对对象数组进行排序?

[英]Sort an array of objects based on times string values?

I have an array of objects 我有一系列对象

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"
  }];

I want to sort data by its time string value so that the required output becomes like this below: 我想按时间字符串值对数据进行排序,以便所需的输出如下所示:

 [{
    "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"
  }]

I have used the sort function with String #localeCompare but still i am not getting the required output 我已经使用了String #localeCompare的sort函数,但是仍然无法获得所需的输出

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

even i used the String#slice() method by which i can be used to generate the valid date string using '1970/01/01' as an arbitrary date still i am getting the required out can anyone give me the way by which i can get the output in this manner Thanks in advance. 即使我使用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))
});

Example: 例:

 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) 

I'd have a functon to turn those times into minutes-since-midnight, something roughly like: 从午夜起,我将有一个功能可以将这些时间转换为分钟,大致类似于:

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);
}

Then the sorting is straightforward: 然后排序很简单:

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

Example: 例:

 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; } 

Classic divide-and-conquer (eg, break the problem into smaller pieces). 经典的分而治之(例如,将问题分解成较小的部分)。

This works (after adding a missing comma): 这有效(添加缺失的逗号后):

 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) 

Normal string comparison is fine for this, but you need to re-arrange the AM or PM at the beginning of the time string(use String#replace method for that). 正常的字符串比较可以解决此问题,但是您需要在时间字符串的开头重新排列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); 

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

With a helper function toMilitary you can change the time to a number between 0 and 2359. Then map the original data to military time and index. 使用辅助功能到军事,您可以将时间更改为0到2359之间的数字。然后将原始数据映射到军事时间和索引。 Then sort on the military time. 然后整理一下军事时间。 And at last reduce the result using the indexes of the sorted set to pick items from the original data. 最后,使用排序集的索引来减少结果,以从原始数据中选择项目。

Following code does not mutate any of the original data. 以下代码不会更改任何原始数据。

  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)) 

I like mplungjan way and it includes the date. 我喜欢mplungjan方式,它包含日期。 It will call the parsing date and time function many times while sorting so I've implemented it instead of military from the previous. 排序时它将多次调用解析日期和时间函数,因此我已经实现了它,而不是以前的实现。 First calculate full date and time for all objects and pair with index, then sort, then pick items from data using the indexes of the sorted result: 首先计算所有对象的完整日期和时间,并与索引配对,然后进行排序,然后使用排序结果的索引从数据中选择项目:

 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)) 

Here's a simple example using moment.js to parse with a custom format : 这是一个使用moment.js解析自定义格式的简单示例:

 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> 

Here's another example which also includes the end time in the sort (if two start date/times are equal): 这是另一个示例,其中还包括排序中的结束时间(如果两个开始日期/时间相等):

 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM