Сортировать список по имени, дате и иерархии

1

Я хочу отсортировать следующий список в следующем порядке:

  1. сначала объектом без какого-либо родителя
  2. то по имени
  3. по годам
  4. по месяцам
  5. связанные объекты должны поступать непосредственно по критериям (2-4).

Так что я хочу достичь, в основном, это древовидная структура как плоский список.

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

function monthYearCheck(a, b) {
    if(a.year < b.year) {
        return -1;
    } else if(a.year > b.year) {
        return 1;
    } else {
        if(a.month < b.month) {
            return -1;
        } else if(a.month > b.month) {
            return 1;
        } else {
            return 0;
        }
    }
}

var sortedArray = nonSortedArray.sort(function (a, b) {
    if(a.name === b.name) {
        return monthYearCheck(a, b);
    } else if(a.name < b.name) {
        return -1;
    } else if(a.name > b.name) {
        return 1;
    }
});   

Это массив перед сортировкой:

[{
    name: "Bottom",
    id: 4,
    parentId: 54,
    month: 6,
    year: 2016,
    value: 16       
},{
    name: "Topp",
    id: 12,
    month: 6,
    year: 2016,
    value: 24
},{
    name: "Middle",
    id: 54,
    parentId: 12,
    month: 5,
    year: 2016,
    value: 14   
},{
    name: "Middle2",
    id: 118,
    parentId: 104,
    month: 6,
    year: 2016,
    value: 4    
},{
    name: "Bottom2",
    id: 5,
    parentId: 54,
    month: 5,
    year: 2016,
    value: 12
},{
    name: "Topp",
    id: 12,
    month: 5,
    year: 2016,
    value: 12
},{
    name: "Middle",
    id: 54,
    parentId: 12,
    month: 6,
    year: 2016,
    value: 4    
},{
    name: "Topp2",
    id: 104,
    month: 5,
    year: 2016,
    value: 12
},{
    name: "Bottom2",
    id: 5,
    parentId: 54,
    month: 6,
    year: 2016,
    value: 2        
}]

Этого я хочу достичь:

[{
    name: "Topp",
    id: 12,
    month: 5,
    year: 2016,
    value: 12
},{
    name: "Topp",
    id: 12,
    month: 6,
    year: 2016,
    value: 24
},{
    name: "Middle",
    id: 54,
    parentId: 12,
    month: 5,
    year: 2016,
    value: 14   
},{
    name: "Middle",
    id: 54,
    parentId: 12,
    month: 6,
    year: 2016,
    value: 4    
},{
    name: "Bottom",
    id: 4,
    parentId: 54,
    month: 6,
    year: 2016,
    value: 16       
},{
    name: "Bottom2",
    id: 5,
    parentId: 54,
    month: 6,
    year: 2016,
    value: 2        
},{
    name: "Bottom2",
    id: 5,
    parentId: 54,
    month: 5,
    year: 2016,
    value: 12
},{
    name: "Topp2",
    id: 104,
    month: 5,
    year: 2016,
    value: 12
},{
    name: "Middle2",
    id: 118,
    parentId: 104,
    month: 6,
    year: 2016,
    value: 4    
}]
Теги:
sorting

2 ответа

1

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

var data = [{ name: "Bottom", id: 4, parentId: 54, month: 6, year: 2016, value: 16 }, { name: "Topp", id: 12, month: 6, year: 2016, value: 24 }, { name: "Middle", id: 54, parentId: 12, month: 5, year: 2016, value: 14 }, { name: "Middle2", id: 118, parentId: 104, month: 6, year: 2016, value: 4 }, { name: "Bottom2", id: 5, parentId: 54, month: 5, year: 2016, value: 12 }, { name: "Topp", id: 12, month: 5, year: 2016, value: 12 }, { name: "Middle", id: 54, parentId: 12, month: 6, year: 2016, value: 4 }, { name: "Topp2", id: 104, month: 5, year: 2016, value: 12 }, { name: "Bottom2", id: 5, parentId: 54, month: 6, year: 2016, value: 2 }]
    .sort(function (a, b) {
        return a.name.localeCompare(b.name) || a.year - b.year || a.month - b.month;
    }),
    tree = function (data, root) {
        var r = [],
            o = {};
        data.forEach(function (a) {
            var temp = { data: [a], children: o[a.id] && o[a.id].children };
            if (o[a.id] && o[a.id].data) {
                o[a.id].data.push(a);
                return;
            }
            o[a.id] = temp;
            if (a.parentId === root) {
                r.push(temp);
            } else {
                o[a.parentId] = o[a.parentId] || {};
                o[a.parentId].children = o[a.parentId].children || [];
                o[a.parentId].children.push(temp);
            }
        });
        return r;
    }(data, undefined),
    result = function getValue(array) {
        return array.reduce(function (r, o) {
            return r.concat(o.data, getValue(o.children || []));
        }, []);
    }(tree);

console.log(result);
console.log(tree); // just how it works ...
.as-console-wrapper { max-height: 100% !important; top: 0; }
0

Вы можете использовать следующее:

var sortedArray = nonSortedArray.sort(function (a, b) {
    return compareParentID(a.parentId, b.parentID) || a.name.localeCompare(b.name) || a.year.localeCompare(b.year) || a.month.localeCompare(b.month);
});

function compareParentID(a, b) {
    if (a == null && b != null) 
        return -1;

    if (a != null && b == null) 
        return 1;

    return a - b;
}

Если элементы имени не равны, то они сортируют их по имени.

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

Просто цепь больше || клаузулы для каждого дополнительного элемента, который вы хотите сравнить, в том порядке, в котором вы хотите их сравнить.

  • 0
    Как это решает мою проблему с сортировкой детей после родителя? Также остерегайтесь использования localCompare, это очень медленно для больших наборов данных.
  • 0
    @Victor Если localeCompare слишком неэффективен для вас, не стесняйтесь писать свои собственные компараторы. Мой первоначальный ответ состоял в том, чтобы дать вам представление о том, как решить проблему. Однако, поскольку это было недостаточно ясно, я предоставил полный ответ выше.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню