Сортировка массива массивов будних дней (JavaScript) - PullRequest
0 голосов
/ 28 августа 2018

Наличие следующего массива (например):

[
 ['Tue', 'Fri'],
 ['Mon'],
 ['Mon', 'Thu', 'Sun'],
 ['Wed', 'Thu', 'Sun'],
 ['Tue', 'Wed']
]

Мне нужно отсортировать это, чтобы получить следующее:

[
 ['Mon'],
 ['Mon', 'Thu', 'Sun'],
 ['Tue', 'Wed'],
 ['Tue', 'Fri'],
 ['Wed', 'Thu', 'Sun']
]

Не означает, сколько дней в массиве может быть - если оно больше 1, остальные должны быть отсортированы соответственно по индексу позиции в неделе.

Как реализовать такую ​​функцию сортировки? Спасибо.

Ответы [ 6 ]

0 голосов
/ 28 августа 2018

Этого можно добиться путем преобразования каждого массива в строковое представление и использования String.prototype.localeCompare() для сортировки:

const input = [['Tue', 'Fri'],['Mon'],['Mon', 'Thu', 'Sun'],['Wed', 'Thu', 'Sun'],['Tue', 'Wed']];

const days = {Mon:'a', Tue:'b', Wed:'c', Thu:'d', Fri:'e', Sat:'f', Sun:'g'};

const sorted = input.sort((a,b) => {
    const [aLoc, bLoc] = [a,b].map(e => e.map(d => days[d]).join(''));
    return aLoc.localeCompare(bLoc);
});

console.log(sorted);
0 голосов
/ 28 августа 2018

Если вы напишите две функции для преобразования имен в значения и значений в имена, это будет одна строка.

function dayvalue (day)
{
  switch (day) {
  case 'Mon': return 0;
  case 'Tue': return 1;
  case 'Wed': return 2;
  case 'Thu': return 3;
  case 'Fri': return 4;
  case 'Sat': return 5;
  case 'Sun': return 6;
  }
}

function dayname (value)
{
  switch (value) {
  case 0: return 'Mon';
  case 1: return 'Tue';
  case 2: return 'Wed';
  case 3: return 'Thu';
  case 4: return 'Fri';
  case 5: return 'Sat';
  case 6: return 'Sun';
  }
}

var days = [
  ['Tue', 'Fri'],
  ['Mon'],
  ['Mon', 'Thu', 'Sun'],
  ['Wed', 'Thu', 'Sun'],
  ['Tue', 'Wed']
];

console.log(days.map(names => names.map(dayvalue)).sort().map(values => values.map(dayname)));
0 голосов
/ 28 августа 2018

Вы можете взять объект с сортируемыми предметами, которые можно сложить в строку.

const
    days = { Mon: 'a', Tue: 'b', Wed: 'c', Thu: 'd', Fri: 'e', Sat: 'f', Sun: 'g' },
    getV = a => a.map(d => days[d]).join('');

var array = [['Tue', 'Fri'], ['Mon'], ['Mon', 'Thu', 'Sun'], ['Wed', 'Thu', 'Sun'], ['Tue', 'Wed']];

array.sort((a, b) => getV(a).localeCompare(getV(b)));

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 28 августа 2018

Я написал функцию compareArray, чтобы определить порядок двух массивов, скажем, ['Tue', 'Wed'] и ['Tue', 'Fri']. а затем использовал его в функции сортировки

var arr = [
 ['Tue', 'Fri'],
 ['Mon'],
 ['Mon', 'Thu', 'Sun'],
 ['Wed', 'Thu', 'Sun'],
 ['Tue', 'Wed']
]

var order = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']


var compareArray = (arr1, arr2) => {
  for(var i=0;i<arr1.length;i++){
     if(!arr2[i]) {return 1}
    if(order.indexOf(arr1[i]) < order.indexOf(arr2[i])) {
       return -1;
   } else if(order.indexOf(arr1[i]) > order.indexOf(arr2[i])){ 
      return 1;
  }
 }
  return 0;
}

arr.sort((a,b) => compareArray(a,b))

console.log(arr)
0 голосов
/ 28 августа 2018

Если вы можете реструктурировать данные, это может помочь.

 let days = [
  {day:'Mon',index:1},
  {day:'Sat',index:6},
  {day:'Sun',index:0},
  {day:'Wed',index:3},
  {day:'Tue',index:2},
  {day:'Thu',index:4},
  {day:'Fri',index:5},
];

days.sort((a,b) => {return a.index > b.index});
0 голосов
/ 28 августа 2018

Это не учитывает каждый случай, но выполняет следующее:

  • использует предварительно описанный объект заказа
    • Использование списка заказов упрощает переключение воскресенья с первого на последний (или имеет некоторые другие заказные / взвешенные заказы)
    • вы не ограничены объектом и можете использовать массив (для извлечения индекса) или Date (для преобразования дня), но я думаю, что объект или набор могут быть более эффективными
  • использует рекурсию для оценки следующего элемента в случае, если существует связь
    • если следующего элемента нет, порядок (_a или _b) по умолчанию равен 0, поскольку отсутствие элемента имеет более высокий приоритет
    • вы можете поставить там чек, чтобы вообще избежать рекурсивного вызова

let order = {
 'Mon':1,
 'Tue':2,
 'Wed':3,
 'Thu':4,
 'Fri':5,
 'Sat':6,
 'Sun':7
}

let arr = [
 ['Tue', 'Fri'],
 ['Mon'],
 ['Mon', 'Thu', 'Sun'],
 ['Wed', 'Thu', 'Sun'],
 ['Tue', 'Wed']
]


let sorted = arr.sort(sortElements)
console.log('sorted:',sorted)


function sortElements(a,b,ndx=0){
  let _a = order[ a[ndx] ] || 0
  let _b = order[ b[ndx] ] || 0
    
  if ( _a === _b && (a.length > ndx || b.length > ndx))
    return sortElements(a,b,ndx+1)
  else
    return _a - _b
}
...