Сортировать массив по месяцам и годам

Мне нужна помощь с сортировкой массива по месяцам и годам для отображения на графике соответственно.

Array1: ['Mar19','Apr18','Jun18','Jul18','May18','Jan19'....];
Desired Output : [....'Apr18','May18','Jun18','Jul18','Jan19','Mar19'];

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

Array2: ['Mar19_value','Apr18_value','Jun18_value','Jul18_value','May18_value'
       ,'Jan19_value'....];

Array2: ['55','2','3','0','21','132'....]; //real values

При monthyear массива monthyear я хочу, чтобы данные в этом массиве переместились на новую позицию в соответствии с позицией monthyear. Как это:

Desired Array1: [....'Apr18','May18','Jun18','Jul18','Jan19','Mar19'];
Desired Array2: [....'Apr18_value','May18_value','Jun18_value','Jul18_value','Jan19_value','Mar19_value'];

Таким образом, я могу выбрать данные позже так:

var label = array[4];
var value = array2[4];

Как это можно сделать?

Ответ 1

Вы можете получить дату в виде сортируемой строки и отсортировать ее.

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

Функция getD возвращает отформатированную строку, беря индекс array0 для сортировки. Внутри функции строка разбита на части месяца и года и заменена представлением ISO 8601. Функция обратного вызова замещающей функции принимает сопоставленные элементы, возвращает массив с отформатированным годом и месяцем объекта с названиями месяцев и соответствующими номерами месяцев. Затем этот массив соединяется и возвращается.

Сортировка происходит по сравнению со String#localeCompare.

var array1 = ['Mar19', 'Apr18', 'Jun18', 'Jul18', 'May18', 'Jan19'],
    array2 = ['Mar19_value', 'Apr18_value', 'Jun18_value', 'Jul18_value', 'May18_value', 'Jan19_value'],
    array3 = ['55', '2', '3', '0', '21', '132'],
    indices = Object
        .keys(array1)
        .sort(function (a, b) {
            function getD(i) {
                var months = { Jan: '01', Feb: '02', Mar: '03', Apr: '04', May: '05', Jun: '06', Jul: '07', Aug: '08', Sep: '09', Oct: '10', Nov: '11', Dec: '12' },
                    s = array1[i];
                return s.replace(/^(...)(.+)$/, (_, m, y) => [y.padStart(4, '0'), months[m]].join('-'));
            }
            return getD(a).localeCompare(getD(b));
        }),
    result = [array1, array3].map(a => indices.map(i => a[i]));
  
result.forEach(a => console.log(...a));

Ответ 2

Вам нужно изменить строку на new Date(dateString) формат new Date(dateString) , например

new Date(Month Date Year)

Обновленный шаблон регулярных выражений для обоих массивов

https://regex101.com/r/h1cm1z/2/

Обновлен массив второй сортировки на основе индекса сортировки первого массива.

var arr1 =  ['Mar19','Apr18','Jun18','Jul18','May18','Jan19'];
var arr2 =['55','2','3','0','21','132'];

function datesort(arr){
 return arr.concat().sort((a,b)=>{
 a = a.replace(/(\d+)(.*)/g,' 1 $1'); // Month 1 YEAR
 b = b.replace(/(\d+)(.*)/g,' 1 $1'); // Month 1 YEAR
  return new Date(a) - new Date(b)
})
}

var after_arr1 =new datesort(arr1);
var after_arr2 = arr1.reduce(function(a,b,c){
     var ind = after_arr1.indexOf(b);
     a[ind] = arr2[c]
     return a
},[]);


console.log(after_arr1.join(','));
console.log(after_arr2.join(','))

Ответ 3

const input = ['Mar19', 'Apr18', 'Jun18', 'Jul18', 'May18', 'Jan19'];

//const output : ['Apr18','May18','Jun18','Jul18','Jan19','Mar19'];
//Can be done easily by using momentjs, darte-fns, but here i will do it natively

const t = {
  Jan: 1,
  Feb: 2,
  Mar: 3,
  Apr: 4,
  May: 5,
  Jun: 6,
  Jul: 7,
  Aug: 8,
  Sep: 9,
  Oct: 10,
  Nov: 11,
  Dec: 12
}
const giveConcatString = (a, t) => {
  const monthPart = a.substr(0, 3)
  const yearPart = a.substr(3)
  return '${yearPart}${t[monthPart]}'
}
const sortedArray = input.sort((a, b) => {
  const concatString = giveConcatString(a, t)
  const concatStringB = giveConcatString(b, t)
  return concatString <= concatStringB ? -1 : 1

})
console.log(sortedArray)

Ответ 4

Для правильного оформления заказа необходимо знать порядок месяцев. Это не в алфавитном порядке, поэтому вы можете использовать массив с порядком месяцев, а затем искать их.

const monthOrder = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec "]

Уже правильно отсортирован и может использоваться вместе с .indexOf(), чтобы получить позицию месяца.

const myArr =  ['Mar19','Apr18','Jun18','Jul18','May18','Jan19'];
const myArr2 = ['Mar19_value','Apr18_value','Jun18_value','Jul18_value','May18_value'
   ,'Jan19_value'];

const monthOrder = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

let sortYearMonth = (a, b) => {
    let monthA = monthOrder.indexOf(a.slice(0,3))
	let yearA = a.slice(3,6)
	let monthB = monthOrder.indexOf(b.slice(0,3))
	let yearB = b.slice(3,6)
	return ('${yearA}-${monthA}' < '${yearB}-${monthB}') ? -1 : ('${yearA}-${monthA}' > '${yearB}-${monthB}') ? 1 : 0
}

let sortedMonths = myArr.sort(sortYearMonth)
let sortedMonths2 = myArr2.sort(sortYearMonth)

console.log(sortedMonths )
console.log(sortedMonths2 )

Ответ 5

Вы можете попробовать этот сырой фрагмент.

var MY = ['Mar19', 'Apr18', 'Jun18', 'Jul18', 'May18', 'Jan19'];
var s = "JanFebMarAprMayJunJulAugSepOctNovDec";
// converting to raw date format
for (i in MY) {
  num = MY[i].match(/\d+/g);
  letr = MY[i].match(/[a-zA-Z]+/g);
  MY[i] = (s.indexOf(letr) / 3 + 1) + '-' + '20' + num;
}
// sorting logic
var sorted = MY.sort(function(a, b) {
  a = a.split("-");
  b = b.split("-")
  return new Date(a[1], a[0], 1) - new Date(b[1], b[0], 1)
});
// converting back to original array after sorting
res = [];
for (i in sorted) {
  var a = sorted[i].split('-');
  res[i] = (s.substr((parseInt(a[0]) - 1) * 3, 3)) + '-' + a[1].substr(2, 2);
}

console.log(res);

Ответ 6

Я использовал lodash для сортировки и метод substring чтобы разделить дату на части месяца и дня

const data = ['Mar20','Mar21', 'Mar01', 'Mar19','Apr18','Jun18','Jul18','May18','Jan19']

const monthMap = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

const sorted = _.sortBy(data, date => monthMap.indexOf(date.substring(0,3)), date => date.substring(3,5))

console.log(sorted)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Ответ 7

let mth = ['Mar19','Apr18','Jun18','Jul18','May18','Jan19'];

mth.sort((itemA, itemB)=>{
   let mthAstr = itemA.slice(0,3)+" 01 "+itemA.slice(3,5);
   let mthA = new Date(mthAstr);
   let mthBstr = itemB.slice(0,3)+" 01 "+itemB.slice(3,5);
   let mthB = new Date(mthBstr);
   if (mthA < mthB)
      return -1;
   if (mthA > mthB)
      return 1;
   return 0;
});

Ответ 8

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

var Array =  ['Mar19','Apr18','Jun18','Jul18','May18','Jan19'];
Array.sort(function(a, b) {
    a = [a.slice(0,3), ' 20', a.slice(3)].join('');
    b = [b.slice(0,3), ' 20', b.slice(3)].join('')
    return new Date() - new Date(b);
});

console.log(Array);

Ответ 9

Я бы предположил, что ваша структура данных неудачна. Работа с общими индексами делает это намного сложнее, чем структура данных, которая их объединяет, например, массив объектов [{label: 'Mar19', value: 55},...].

Если ваши данные поступают из вышестоящего решения, которое вы не можете контролировать, вы все равно можете управлять им в своей работе, конвертируя перед использованием. (И если вам действительно нужно обратиться обратно, чтобы передать другим.)

Распространенным названием для функции, объединяющей два массива, является zip - представьте, что она действует как молния. Эта версия использует тот, который принимает функцию, чтобы сказать, как парные элементы должны быть объединены. (В другом месте такую функцию можно назвать zipWith.)

Здесь sortArraysByDate вызывает zip передавая функцию, которая превращает 'Mar19' и 55 в {label: 'Mar19, value: 55, month: 'Mar', year: 19} используя dateFields для извлечения месяца и года из этой метки, затем сортирует эти используя простую dateSort

const months = {Jan: 1, Feb: 2, Mar: 3, Apr: 4,  May: 5,  Jun: 6,
                Jul: 7, Aug: 8, Sep: 9, Oct: 10, Nov: 11, Dec: 12}
                
const dateFields = (d) => ({
  month: d.slice(0, 3),
  year: Number(d.slice(3))
})

const dateSort = ({month: m1, year: y1}, {month: m2, year: y2}) =>
  (y1 - y2) || (months[m1] - months[m2])

const zip = (fn, a1, a2) => a1.map((a, i) => fn(a, a2[i]))

const sortArraysByDate = (a1, a2) =>
  zip((label, value) => ({label, value, ...dateFields(label)}), a1, a2)
    .sort(dateSort)
    .map(({label, value}) => ({label, value}))


const Array1 = ['Mar19','Apr18','Jun18','Jul18','May18','Jan19'];
const Array2 =   ['55','2','3','0','21','132']; //real values

const result = sortArraysByDate(Array1, Array2)

console.log(result)