Reputation: 3129
I am sorting an array of objects and having an issue keeping the empty objects in order, below will sort by SectionName
(() => {
const items = [{
ID: 20,
SectionName: "Cabinet"
},
{
ID: 0,
SectionName: ""
},
{
ID: 0,
SectionName: ""
},
{
ID: 20,
SectionName: "Cabinet"
},
{
ID: 2,
SectionName: "Frame"
},
{
ID: 0,
SectionName: ""
},
{
ID: 3,
SectionName: "Alt"
},
{
ID: 4,
SectionName: "Upper"
},
{
ID: 0,
SectionName: ""
},
{
ID: 0,
SectionName: ""
},
{
ID: 0,
SectionName: ""
},
{
ID: 5,
SectionName: "Lower"
}
];
//items.forEach((e, i) => {
// console.log(e);
//});
// sort by name
items.sort(function(a, b) {
let nameA = a.SectionName.toUpperCase();
let nameB = b.SectionName.toUpperCase();
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
return 0;
});
console.table(items);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
but doesn't keep the empty objects in place before the sort, what I am trying to get it to sort like is
{ID: 3, SectionName: "Alt"},
{ID: 20, SectionName: "Cabinet"},
{ID: 0, SectionName: ""},
{ID: 0, SectionName: ""},
{ID: 20, SectionName: "Cabinet"},
{ID: 2, SectionName: "Frame"},
{ID: 0, SectionName: ""},
{ID: 5, SectionName: "Lower"},
{ID: 0, SectionName: ""},
{ID: 0, SectionName: ""},
{ID: 0, SectionName: ""} ,
{ID: 4, SectionName: "Upper"}
Upvotes: 1
Views: 794
Reputation: 122037
You could just filter out those items where the SectionName
is empty, sort that result and then insert back the empty ones into the sorted output.
const items = [{"ID":20,"SectionName":"Cabinet"},{"ID":0,"SectionName":""},{"ID":0,"SectionName":""},{"ID":20,"SectionName":"Cabinet"},{"ID":2,"SectionName":"Frame"},{"ID":0,"SectionName":""},{"ID":3,"SectionName":"Alt"},{"ID":4,"SectionName":"Upper"},{"ID":0,"SectionName":""},{"ID":0,"SectionName":""},{"ID":0,"SectionName":""},{"ID":5,"SectionName":"Lower"}]
const sorted = items
.filter(({ SectionName }) => SectionName)
.sort((a, b) => a.SectionName.localeCompare(b.SectionName))
items.forEach((e, i) => {
if (!e.SectionName) sorted.splice(i, 0, e)
})
console.log(sorted)
Upvotes: 1
Reputation: 386560
This is an approach by using sort
directly, but shaping the access with a Proxy
for length
and the indices.
const
sort = (array, sortFn, filterFn = _ => true) => {
const indices = [...array.keys()].filter(i => filterFn(array[i]));
new Proxy(array, {
get (target, prop) {
if (isFinite(prop)) return target[indices[prop]];
if (prop === 'length') return indices.length;
return target[prop];
},
set (target, prop, receiver) {
target[indices[prop]] = receiver;
return true;
}
})
.sort(sortFn);
return array;
},
items = [{ ID: 20, SectionName: "Cabinet" }, { ID: 0, SectionName: "" }, { ID: 0, SectionName: "" }, { ID: 20, SectionName: "Cabinet" }, { ID: 2, SectionName: "Frame" }, { ID: 0, SectionName: "" }, { ID: 3, SectionName: "Alt" }, { ID: 4, SectionName: "Upper" }, { ID: 0, SectionName: "" }, { ID: 0, SectionName: "" }, { ID: 0, SectionName: "" }, { ID: 5, SectionName: "Lower" }];
console.log(...sort(
items,
(a, b) => a.SectionName.localeCompare(b.SectionName),
({ SectionName }) => SectionName
));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1