1

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"}
1
  • Array.prototype.sort() lets you compare two items against each other and lets you determine which one has the higher sorting order. It seems that what you're trying to achieve goes beyond checking only two objects, but rather evaluating the entire array. I don't think Array.prototype.sort() will be enough here. What is the logic for the requested order? It seems a bit arbitrary. Commented Mar 24, 2021 at 13:57

2 Answers 2

1

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)

Sign up to request clarification or add additional context in comments.

1 Comment

That was easier to understand, even though Nina's answer has me kinda confused on the approach she took and was going to accept her answer, but I need to accept your instead as it is less confusing and more understandable. Good Job and thanks!
1

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; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.