фильтрация вложенных массивов по дате

#javascript #reactjs #momentjs

Вопрос:

У меня есть массив из 273 массивов, каждый из которых содержит данные о футбольном матче регулярного чемпионата НФЛ. Одной из записей данных в массиве является дата начала игры. Я пытаюсь отфильтровать свой массив в поддиапазоны, содержащие все игры за определенную неделю.

Другими словами, я хочу, чтобы в итоге получилось 17 массивов, каждый из которых представляет неделю сезона НФЛ.

Мои массивы выглядят так ["2021-09-09", "DAL", "TB", ".55", .".45"] .

Я могу использовать momentjs и написать функцию, которая проверяет, находится ли дата в массиве между двумя указанными датами.

 for(const element of data){
    if(moment(element[0]).isBetween("2021-09-08", "2021-09-14")){
        weekOneArray.push(element);
    }
 }
 

Это прекрасно работает, однако мне придется жестко if закодировать заявление на все 17 недель сезона.

Кто — нибудь может придумать способ упростить мою функцию, чтобы я мог переключаться на недели сезона?

Комментарии:

1. Используйте moment().unix (), чтобы получить метку времени Unix, которая представляет собой число. Затем вы можете использовать его для сортировки массива.

2. Не нужно использовать момент; просто используйте element[0] > startDay amp;amp; element[0] < endDay , и даты в формате гггг-ММ-дд будут сортироваться естественным образом.

3. @HereticMonkey Разве мне все еще не нужно будет жестко указать дату начала и окончания?

4. Не можете ли вы сгенерировать все даты недели для сезона, а затем отправить свои данные на основе этих дат?

5. moment(...).week() и lodash.groupBy() может сделать его чистым и понятным

Ответ №1:

Последнее обновление / Самое простое решение с Lodash

С Lodash (как упоминал авинаш) и моментами это было бы только:

 const sortGamesAlt = (arrayOfGames) => {
  return groupBy(arrayOfGames, (game) =>
    moment(game[0]).isoWeekday(1)
  );
};
 

Обновленный

Вы можете проверить этот код и настроить его в соответствии с вашими потребностями: https://codesandbox.io/s/crazy-mestorf-6yivl

После тестирования предыдущего кода я заметил некоторые детали, он может работать с этим:

 const sortGames = (arrayOfGames) => {
  const sortedGames = {};

  arrayOfGames.forEach((game) => {
    const startDate = moment(game[0]).isoWeekDay(1); // startOfWeek on Monday
    sortedGames[startDate] = sortedGames[startDate]
      ? [...sortedGames[startDate], game]
      : [game];
  });

  const sortedInfo = Object.entries(sortedGames).sort(
    (a, b) => new Date(a[0]) - new Date(b[0])
  );

  return sortedInfo;
};
 

Получение:

  const arrayOfGames = [
    ["2021-09-09", "DAL", "TB", ".55", ".45"],
    ["2021-10-09", "X", "Y", ".55", ".45"],
    ["2021-11-09", "Z", "A", ".55", ".45"],
    ["2021-09-12", "B", "C", ".55", ".45"],
    ["2021-09-10", "D", "E", ".55", ".45"]
  ]; 
 

Это вернется:

 ['Mon Nov 08 2021 00:00:00 GMT-0300', ['2021-11-09', 'Z', 'A', '.55', '.45']]
['Mon Oct 04 2021 00:00:00 GMT-0300', ['2021-10-09', 'X', 'Y', '.55', '.45']]
['Mon Sep 06 2021 01:00:00 GMT-0300', ['2021-09-09', 'DAL', 'TB', '.55', '.45'], ['2021-09-10', 'D', 'E', '.55', '.45'], '2021-09-12', 'B', 'C', '.55', '.45']]
 

СТАРАЯ / Краткая идея

Вы можете сделать что-то вроде этого:

 const arrayOfGames = [["2021-09-09", "DAL", "TB", ".55", ".45"], ["2021-10-09", "X", "Y", ".55", ".45"], ["2021-11-09", "Z", "A", ".55", ".45"], ["2021-09-12", "B", "C", ".55", ".45"]] // it'll have all your arrays: ["2021-09-09", "DAL", "TB", ".55", .".45"]
const sortedGames = {};

arrayOfGames.forEach(game => {
  // startOfWeek returns Sunday, so start on Monday if you add one day
  const startDate = moment(game[0]).startOf('week').add(1, 'days') 
  // endOfWeek returns Saturday, so finish on Sunday if you add one day
  const endDate = moment(game[0]).endOf('week').add(1, 'days')
  // Insert with the other games or JUST define new array only with this game
  sortedGames[startDate] = sortedGames[startDate] ? [...sortedGames[startDate], game] : [game]
})

Object
  // return an array of [startDateOfWeek, arrayOfGamesOfThatWeek]
  .entries(sortedGames)                             
  // sort the array based on the startDate
  .sort((a, b) => new Date(b[0]) - new Date(a[0]))  
  // Just return the array of games already sorted (you can also return the date if you want and ignore this line
  .map(a => a[1])                                   

// Returns [[["2021-11-09","Z","A",".55",".45"]],[["2021-10-09","X","Y",".55",".45"]],[["2021-09-12","B","C",".55",".45"]],[["2021-09-09","DAL","TB",".55",".45"]]]'
 

Ответ №2:

Вам нужно создать новый массив со всеми неделями из вашего исходного массива, поскольку все ваши недели относятся к одному и тому же году, вы можете использовать номер недели в году для их определения. Этот код поможет вам узнать номер недели

 currentdate = new Date();
var oneJan = new Date(currentdate.getFullYear(),0,1);
var numberOfDays = Math.floor((currentdate - oneJan) / (24 * 60 * 60 * 1000));
var result = Math.ceil(( currentdate.getDay()   1   numberOfDays) / 7);

 

После этого вам нужно создать еще один массив, который будет вашим конечным результатом через 17 недель.

Вам нужно зациклить свой начальный массив и отсортировать его до конечного массива в соответствии с вашим массивом номеров недель.