【问题标题】:How to filter data based on date?如何根据日期过滤数据?
【发布时间】:2019-06-21 09:14:23
【问题描述】:

我有一个数组,

var data = [
    { id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
    { id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
    { id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
    { id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
    { id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
    { id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
    { id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
    { id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
    { id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" }
    ];
    
    
data.forEach(function(result) {
   console.log(result.jobCategoryWithFromDate);
});

在控制台中给出上述结果..

在 foreach 中,我需要返回具有最新日期的 jobCategoryWithFromDate

所以预期的结果是,(下同)..

ASSIST.. / Assistance [valid from 2019-01-01]
PROF.. / Professional [valid from 2019-01-01]
SEN.. / Senior [valid from 2019-01-01]

以上是预期的结果,没有任何变化,只需要过滤结果并返回jobCategoryWithFromDate返回具有最新日期的唯一值..

尽管名称重复,但过滤器需要根据日期(最新)处理..

编辑:

我已经接受了答案,但后来我才知道它在所有情况下都不起作用,很抱歉没有完全测试它..

不知道我的解释是否出错,但如果用户名相同,则需要根据日期进行过滤,否则需要显示具有任何日期的唯一用户。

例如:

    var data = [
        { id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
        { id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
        { id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
        { id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
        { id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
        { id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
        { id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
        { id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
        { id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" },
        { id: 10, jobCategoryWithFromDate: "Jun.. / Junior  [valid from 2018-01-01]" },
        { id: 11, jobCategoryWithFromDate: "Usr.. / User [valid from 2019-01-01]" },
        { id: 12, jobCategoryWithFromDate: "Man.. / Manager [valid from 2017-05-01]" }
    ];

function extractDate(string){
  return string.match(/[0-9]+-[0-9]+-[0-9]+/g);
}

var result = data.reduce((newestDates, currentItem)=>{
  if (newestDates.length===0) newestDates.push(currentItem);
  else {
    const dateDifference = new Date(extractDate(newestDates[0].jobCategoryWithFromDate)) - new Date(extractDate(currentItem.jobCategoryWithFromDate));
    
    if (dateDifference===0) newestDates.push(currentItem); // push items with the same date as newest found
    else if (dateDifference <= 0) newestDates = [currentItem]; // if item has newer date the original array gets replaced with one containing just this item
    // ignore case dateDifference >= 0 because we do not need to do anything with dates older than the newest found
  }
  return newestDates;
},[]);

console.log(result);

在此 sn-p 中查看最后三个值,它们的用户名不同,但与以前的记录具有相同的日期..

这里的预期结果是我需要获取所有最后三个记录以及以上三个记录,因为它们是不同的用户,比如

ASSIST.. / Assistance [valid from 2019-01-01]
PROF.. / Professional [valid from 2019-01-01]
SEN.. / Senior [valid from 2019-01-01]
Jun.. / Junior  [valid from 2018-01-01]
Usr.. / User [valid from 2019-01-01]
Man.. / Manager [valid from 2017-05-01]

【问题讨论】:

  • 有什么想法或进展吗?
  • @Lain,尝试将字符串存储到数组中,就像这里 codepen.io/anon/pen/dBvoWQ 一样,但它不是预期的。我需要通过在 foreach 中过滤来返回字符串。
  • 你能影响对象的结构吗?就像将 from 部分(=date)放在自己的财产中?最好将其保存在刻度而不是 yyyy-mm-dd 中?
  • @Lain,不,我不能,它来自后端,我只需要根据最新日期进行过滤并需要显示每个独立的..

标签: javascript


【解决方案1】:

假设日期格式为YYYY-MM-DD,您只需从每个元素中提取包含日期的部分字符串并从中创建日期对象

编辑:似乎您想要的是获取每个用户的最后日期,而不是只获取具有最新日期的条目数组,编辑 sn-p 以匹配它(您可以如果您想要不同的比较来区分用户,请编辑提取名称的正则表达式的一部分)

var data = [
    { id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
    { id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
    { id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
    { id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
    { id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
    { id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
    { id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
    { id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
    { id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" },
    { id: 10, jobCategoryWithFromDate: "Jun.. / Junior  [valid from 2018-01-01]" },
    { id: 11, jobCategoryWithFromDate: "Usr.. / User [valid from 2019-01-01]" },
    { id: 12, jobCategoryWithFromDate: "Man.. / Manager [valid from 2017-05-01]" }
];
    
function extractNameNDate(string){
  return [string.match(/^\w+/), string.match(/[0-9]+-[0-9]+-[0-9]+/g)];
}

var result = data.reduce((newestDates, currentItem)=>{
  const [user, date] = extractNameNDate(currentItem.jobCategoryWithFromDate);
  if (newestDates[user]) {
    // compare dates for given user
    const [storedUser, storedDate] = extractNameNDate(newestDates[user].jobCategoryWithFromDate);
    const dateDifference = new Date(storedDate) - new Date(date);
    
    if (dateDifference <= 0) newestDates[user] = currentItem;
    
  } else {
    newestDates[user]=currentItem;
  }
  return newestDates;
},{});

result = Object.values(result);

console.log(result);

这是一个经过编辑的版本,用于匹配字符串的整个第一部分,直到 [] 大括号

var data = [
    { id: 1, jobCategoryWithFromDate: "01-05 Data Specialist [valid from 2019-01-01]" },
    { id: 2, jobCategoryWithFromDate: "01-05 Support [valid from 2019-01-01]" },
    { id: 3, jobCategoryWithFromDate: "03-04 Technician [valid from 2019-01-01]" },
    { id: 4, jobCategoryWithFromDate: "05 Engineer [valid from 2019-01-01]" },
    { id: 5, jobCategoryWithFromDate: "05 Technician [valid from 2019-01-01]" },
    { id: 6, jobCategoryWithFromDate: "05 Technologist [valid from 2019-01-01]" },
    { id: 7, jobCategoryWithFromDate: "06 Engineer [valid from 2019-01-01]" },
    { id: 8, jobCategoryWithFromDate: "06-07 Sr. Technician [valid from 2019-01-01]" },
    { id: 9, jobCategoryWithFromDate: "Intern [valid from 2019-01-01]" },
    { id: 10, jobCategoryWithFromDate: "06-07 Support  [valid from 2019-01-01]" },
    { id: 11, jobCategoryWithFromDate: "06-07 Technologist [valid from 2019-01-01]" },
    { id: 12, jobCategoryWithFromDate: "07 Engineer [valid from 2019-01-01]" },
    { id: 13, jobCategoryWithFromDate: "08 Senior [valid from 2019-01-01]" },
    { id: 14, jobCategoryWithFromDate: "08-09 Support [valid from 2019-01-01]" },
    { id: 15, jobCategoryWithFromDate: "09 Senior [valid from 2019-01-01]" },
    { id: 16, jobCategoryWithFromDate: "10-11 Principal [valid from 2019-01-01]" },
    { id: 17, jobCategoryWithFromDate: "12-13 Sr. Principal [valid from 2019-01-01]" },
    { id: 18, jobCategoryWithFromDate: "14 Vice President [valid from 2019-01-01]" },
    { id: 19, jobCategoryWithFromDate: "15 President [valid from 2019-01-01]" }
];
    
function extractNameNDate(string){
  return [string.match(/[^\/]*/), string.match(/[0-9]+-[0-9]+-[0-9]+/g)];
}

var result = data.reduce((newestDates, currentItem)=>{
  const [user, date] = extractNameNDate(currentItem.jobCategoryWithFromDate);
  if (newestDates[user]) {
    // compare dates for given user
    const [storedUser, storedDate] = extractNameNDate(newestDates[user].jobCategoryWithFromDate);
    const dateDifference = new Date(storedDate) - new Date(date);
    
    if (dateDifference <= 0) newestDates[user] = currentItem;
    
  } else {
    newestDates[user]=currentItem;
  }
  return newestDates;
},{});

result = Object.values(result);

console.log(result);

【讨论】:

  • 我的预期结果是 ASSIST.. / Assistance [valid from 2019-01-01] PROF.. / Professional [valid from 2019-01-01] SEN.. / Senior [valid from 2019-01-01] inside foreach.. 这里您的解决方案显示所有日期..
  • 我需要在 foreach 中获取结果,这意味着在迭代时它应该检查条件并返回三个字符串,例如 ASSIST.. / Assistance [valid from 2019-01-01] PROF.. / Professional [valid from 2019-01-01] SEN.. / Senior [valid from 2019-01-01] ...
  • 我已经编辑了我的问题,你能帮帮我吗,我只是使用了我的解决方案,如果有任何日期的唯一用户(也与以前的用户日期匹配),它就不起作用..你能帮忙吗我在里面..
  • 如果值为Surveyor [valid from 2017-05-01]并且文本前没有../,您能否再给我一部分上述解决方案??
  • 感谢您的更新,但看看小提琴jsfiddle.net/gd5jmqke 我只复制了您的代码,但预期的结果是它需要提供所有 7 个项目,但它只显示 5 个项目.. 见控制台结果..每个对象都有不同的名称,但它只显示 5..
【解决方案2】:

我会先找到最新的日期,然后在数组中过滤具有该日期的对象。这将只返回日期最高的对象:

var data = [
  { id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
  { id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
  { id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
  { id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
  { id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
  { id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
  { id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
  { id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
  { id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" }
];

/* Add new property to data objects to store the "valid from" timestamp - Avoids parsing the text twice */
data.forEach(function(element, index, array) {
  var dateText = element.jobCategoryWithFromDate.match(/\[valid from (\d{4}-\d{2}-\d{2})\]$/)[1];
  array[index].fromDateTimestamp = +(new Date(dateText));
});

/* Get the highest value (the latest date) */
var max = data.reduce(function(currentMax, value) {
  return Math.max(currentMax, value.fromDateTimestamp);
}, 0);

/* Filter the data array to only include objects with the latest date */
var newData = data.filter(function(value) {
  return value.fromDateTimestamp === max;
});

console.log(newData);

【讨论】:

    【解决方案3】:

    您可以应用正则表达式从字符串jobCategoryWithFromDate 中提取日期。然后按日期排序,你会得到最新的结果。

    var data = [
        { id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
        { id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
        { id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
        { id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
        { id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
        { id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
        { id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
        { id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
        { id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" }
        ];
    
    var result= data.map(d => ({...d, date: d.jobCategoryWithFromDate.match(/(\d{1,4}([.\-/])\d{1,2}([.\-/])\d{1,4})/g)[0]}))..sort((a, b)=> new Date(b.date) - new Date(a.date))
    
    console.log(result)
    

    【讨论】:

      【解决方案4】:

      你可以使用一个简单的 reduce 来做到这一点, 您可以通过存储数组和 currentMaxDateTS 来改进减少,而不是在每次迭代中重新计算时间戳。

      如果您需要有关此代码 sn-p 的更多解释,请不要犹豫

      const data = [
          { id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
          { id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
          { id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
          { id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
          { id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
          { id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
          { id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
          { id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
          { id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" }
          ];
      
      // Function returning the date string inside  [valid from 2017-05-01]
      const getDateFromJobCategory = (jobCategoryWithFromDate) =>  jobCategoryWithFromDate.match(/[0-9]+-[0-9]+-[0-9]+/g);
      
      
      const filteredData = data.reduce((acc, data) => {
        // Get data date in timestamp
        const dataDateString = getDateFromJobCategory(data.jobCategoryWithFromDate);
        const dataDateTS = new Date(dataDateString).getTime();
        // Get current max date in timestamp
        const currentMaxDate = getDateFromJobCategory(acc[0]);
        const currentMaxDateTS = new Date(currentMaxDate).getTime()
      
        return dataDateTS > currentMaxDateTS ? [data.jobCategoryWithFromDate] : dataDateTS === currentMaxDateTS ? [...acc, data.jobCategoryWithFromDate] : acc
      
      }, ["[valid from 0001-01-01]"]);
      
         const finalResult = filteredData.forEach(jobCategoryWithFromDate => 
         console.log(jobCategoryWithFromDate))

      【讨论】:

      • 我需要在 foreach 中获取结果,而不是这样,这意味着在迭代时它应该检查条件并返回三个字符串,例如 ASSIST.. / Assistance [valid from 2019-01-01] PROF.. / Professional [valid from 2019-01-01] SEN.. / Senior [valid from 2019-01-01] ...
      • 我不想要像你这样的字符串数组,普通字符串。希望你明白我的意思,我需要在 foreach 中返回它。
      • 我编辑了我的答案,结果应该是问的:) 我只是使用相同的算法,然后在过滤数据后对其进行 forEach。
      【解决方案5】:

      您可以通过使用正则表达式提取日期来使用简单的排序,然后使用递归函数检查是否有多个相同的日期:

      var data = [
          { id: 1, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2017-05-01]" },
          { id: 2, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2018-01-01]" },
          { id: 3, jobCategoryWithFromDate: "ASSIST.. / Assistance [valid from 2019-01-01]" },
          { id: 4, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2017-05-01]" },
          { id: 5, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2018-01-01]" },
          { id: 6, jobCategoryWithFromDate: "PROF.. / Professional [valid from 2019-01-01]" },
          { id: 7, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2018-01-01]" },
          { id: 8, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2019-01-01]" },
          { id: 9, jobCategoryWithFromDate: "SEN.. / Senior [valid from 2017-05-01]" }
      ];
      
      const getDate = date => +date.match(/[0-9]{4}-[0-9]{2}-[0-9]{2}/g)[0].split('-').join('')
      
      data = data.sort(({jobCategoryWithFromDate:date1}, {jobCategoryWithFromDate:date2}) => getDate(date2) - getDate(date1))
      
      const getRecent = (data, i=0) => getDate(data[i].jobCategoryWithFromDate) === getDate(data[i + 1].jobCategoryWithFromDate) ? [data[i], ...getRecent(data, i+1)] : [data[i]]
      
      getRecent(data).forEach(obj => console.log(obj))

      【讨论】:

      • 我的预期结果是ASSIST.. / Assistance [valid from 2019-01-01] PROF.. / Professional [valid from 2019-01-01] SEN.. / Senior [valid from 2019-01-01] inside foreach..
      • 我需要在 foreach 中获取结果,这意味着在迭代时应该检查条件并返回三个字符串,例如 ASSIST.. / Assistance [valid from 2019-01-01] PROF.. / Professional [valid from 2019-01-01] SEN.. / Senior [valid from 2019-01-01] ...
      • 不能在foreach里面做吗??在我的真实应用程序中,我从模板中迭代它并调用一个getter函数,该函数将获取给定的每个单独的值,我需要在该函数中过滤它..所以这里它需要在foreach里面..
      • @ManirajfromKarur 我不太确定我明白你为什么需要 foreach,现在看看我的代码。
      • 简单来说,您是否可以像我在问题中提到的那样在 foreach 内部提供解决方案。所以在result.jobCategoryWithFromDate 的 foreach 内部我们得到字符串,我需要在这个函数中检查它本身..原因是我没有提到的数组,它是动态的..从模板中,我在 ng-repeat 中调用这个函数,比如 {{ getData }} 并且这个函数只会有 foreach 中提到的代码问题..所以需要处理foreach里面的事情..
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      • 1970-01-01
      • 2018-05-17
      • 2021-02-05
      • 2015-11-06
      相关资源
      最近更新 更多