Проблема сортировки массива объектов по дате и времени в Javascript - допускаются нулевые значения - PullRequest
2 голосов
/ 01 августа 2010

Я работаю с массивом объектов в Javascript и мне нужно отсортировать их по дате и времени.Вот настройки:

место

  • название
  • дата (необязательно)
  • время (необязательно)

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

В настоящее время в разных браузерах все по-другому.Вот код (предположим, у меня есть дескриптор массива _places и объекта _list):

var _orderByDate = function (e) {
    YUE.preventDefault(e); // yui
    _places.sort(function (a, b) {
        var dateA = new Date(a.date),
            dateB = new Date(b.date);
        if ((!dateA === null) && (dateB === null)) return 0; //they're both null and equal
        else if ((dateA === null) && (dateB != null)) return -1; //move a downwards
        else if ((dateA != null) && (dateB === null)) return 1; //move b downwards
        else if ((dateA == dateB)) return (a.time > b.time) ? 1 : ((b.time > a.time) ? -1 : 0);
        else return (dateA > dateB) ? 1 : ((dateB > dateA) ? -1 : 0);
    });
    _list.updatePlaces(_places);
}

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

В любом случае, в Chrome список, кажется, сортируется в случайном порядке, и он продолжает сортировать по-разному каждыйраз я выполняю функцию _orderByDate.В Safari он сортируется в основном правильно с первого раза, но ставит одно нулевое место даты в верхней части списка.В Firefox вообще ничего не происходит.

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

Одна вещь, на которую следует обратить внимание, если я исключу тип даты из функции, чтобы он сортировал элементы как строки, он работал правильно ...но это означает, что 1/10/2011 будет сортироваться до 01.01.2011, поэтому я думаю, что мне нужен там тип даты.

Есть идеи, что происходит не так?Есть ли более умный способ сделать то, что я пытаюсь сделать?

РЕДАКТИРОВАТЬ: Добавление значений журнала

Первый вид (Chrome):

  • 08/01/2010
  • null
  • null
  • 08.03.2013
  • null
  • null
  • null
  • null
  • 7/01 /2010
  • null
  • null
  • null

Второй сорт (хром):

  • 08/01 /2010
  • null
  • null
  • null
  • 07/01/2010
  • null
  • null
  • null
  • null
  • null
  • 8/03/2010
  • null
  • null

Ответы [ 3 ]

3 голосов
/ 02 августа 2010

Вы можете значительно упростить алгоритм сортировки, если предварительно обработаете массив так, чтобы он имел числовое представление столбца, по которому вы хотите отсортировать.

Добавьте столбец в таблицу, котораянапример, содержит UTC-эквивалент дат.Затем вы можете безопасно отсортировать массив по свойству UTC, но вы по-прежнему будете отображать строковое значение.

for (var idx in _places)
    _places[idx].UTC = _places[idx].date ? new Date(_places[idx].date).UTC() : 0;

_places.sort(function(a, b)
{
    return a.UTC > b.UTC ? 1 : a.UTC < b.UTC ? -1 : 0;
});

Если вы не хотите использовать объект Date (даты до 1970 года):

for (var idx in _places)
{
    var row = _places[idx];
    if (!row.date)
    {
        row.sortable = 0;
        continue;
    }
    var date = row.date.split('/');
    row.sortable = 10000 * parseInt(date[2]) + 100 * parseInt(date[0]) + parseInt(date[1]); // year, month, day
}

_places.sort(function(a, b)
{
    return a.sortable > b.sortable ? 1 : a.sortable < b.sortable ? -1 : 0;
});

Конечно, это предполагает, что ваши даты всегда будут иметь одинаковый формат M / D / Y.

Вот приведенный выше алгоритм в действии: http://jsfiddle.net/krNnn/

3 голосов
/ 01 августа 2010

[ Посмотреть в действии ]

_places.sort(function (a, b) {
    var dateA = new Date(a.date + a.time), // merge the date & time
        dateB = new Date(b.date + b.time); // depending on the format
    if (!a.date && b.date) return 1;
    else if (a.date && !b.date) return -1;
    else if (dateA === dateB) return 0;
    else return (dateA > dateB) ? 1 : (dateB > dateA ? -1 : 0);
});
0 голосов
/ 02 августа 2010

Хорошо, мы заняты и создали довольно сложную функцию, которая работает во всех браузерах. Некоторые из требований, которые у нас были, были довольно особенными (даты в далеком прошлом, нужно отсортировать нулевые даты внизу, подгруппировать по времени) Вот что мы сделали:

         var _orderByDate = function(e) {
            YUE.preventDefault(e);
            _places.sort(function(a,b) {

                var Ay, Am, Ad, By, Bm, Bd;
                var Ah, Am, Bh, Bm;

                var dateA = a.date.split("/"); 
                if( !dateA.length || dateA.length != 3 || isNaN(dateA[0]) ||
                    isNaN(dateA[1]) || isNaN(dateA[2]) ) {
                    dateA = -1;
                } else {
                    Ay = parseInt(dateA[2]);
                    Am = parseInt(dateA[0]);
                    Ad = parseInt(dateA[1]);
                }

                var dateB = b.date.split("/"); 
                if( !dateB.length || dateB.length != 3 || isNaN(dateB[0]) || 
                    isNaN(dateB[1]) || isNaN(dateB[2]) ) {
                    dateB = -1;
                } else {
                    By = parseInt(dateB[2]);
                    Bm = parseInt(dateB[0]);
                    Bd = parseInt(dateB[1]);
                }

                // null checks
                if(dateA == -1 && dateB == -1) return 0;
                if(dateA == -1 && dateB != -1) return 1;
                if(dateA != -1 && dateB == -1) return -1;

                // year check
                if(Ay > By) return  1;
                if(By > Ay) return -1;

                // month check
                if(Am > Bm) return  1;
                if(Bm > Am) return -1;

                // day check
                if(Ad > Bd) return  1;
                if(Bd > Ad) return -1;


                var timeA = a.time.split(":");
                if( !timeA.length || timeA.length != 2 || isNaN(timeA[0]) ) {
                    timeA = -1;
                } else {
                    if( timeA[1].match(/am/) ) {
                        Ah = parseInt(timeA[0]);
                        Am = parseInt(timeA[1].match(/\d+/));
                    } else if( timeA[1].match(/pm/) ) {
                        Ah = parseInt((timeA[0] * 1) + 12);
                        Am = parseInt(timeA[1].match(/\d+/));
                    }
                }
                var timeB = b.time.split(":");
                if( !timeB.length || timeB.length != 2 || isNaN(timeB[0]) ) {
                    timeB = -1;
                } else {
                    if( timeB[1].match(/am/) ) {
                        Bh = parseInt(timeB[0]);
                        Bm = parseInt(timeB[1].match(/\d+/));
                    } else if( timeB[1].match(/pm/) ) {
                        Bh = parseInt((timeB[0] * 1) + 12);
                        Bm = parseInt(timeB[1].match(/\d+/));
                    }
                }

                // null time checks
                if(timeA == -1 && timeB == -1) return 0;
                if(timeA == -1 && timeB != -1) return 1;
                if(timeA != -1 && timeB == -1) return -1;

                // hour check
                if(Ah > Bh) return  1;
                if(Bh > Ah) return -1;

                // minute check
                if(Am > Bm) return  1;
                if(Bm > Am) return -1;

                return 0;
            } );

            _list.updatePlaces(_places);
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...