0

StackBlitz demo

I am sorting an array for an *ngFor on my Angular application. So far my array is being sorted on sortId value in ascending order. It then sorts the objects with sordId: null back into the array in its original indices position, result below:

Row 1 - Sort ID: null - original array position: 1
Row 2 - Sort ID: null - original array position: 2
Row 3 - Sort ID: null - original array position: 3
Row 4 - Sort ID: 1 - original array position: 8
Row 5 - Sort ID: null - original array position: 5
Row 6 - Sort ID: null - original array position: 6
Row 7 - Sort ID: 4 - original array position: 7
Row 8 - Sort ID: 5 - original array position: 4

.ts method

this.fieldsList = this.users
  .filter(x => x.sortId)
  .sort((a, b) => a.sortId - b.sortId);

this.users.forEach((x, i) => {
  if (x.sortId === null) this.fieldsList.splice(i, 0, x);
});

What I need it to do is for sortID to take priority over the null values. But the null values keep their original indice number/order unless there is a sortId that takes its place. So the example above will be the expected results below:

Row 1 - Sort ID: 1 - original array position: 8
Row 2 - Sort ID: null - original array position: 1
Row 3 - Sort ID: null - original array position: 2
Row 4 - Sort ID: 4 - original array position: 7
Row 5 - Sort ID: 5 - original array position: 4
Row 6 - Sort ID: null - original array position: 3
Row 7 - Sort ID: null - original array position: 4
Row 8 - Sort ID: null - original array position: 5
5
  • Do you want Sort ID to be equal to index + 1 in the output? Like, Sort ID: 1 is at index = 0, Sort ID: 4 is at 3 etc. Commented Jul 30, 2021 at 10:33
  • sortID will be equal to index+1 Commented Jul 30, 2021 at 10:51
  • 1
    What I need it to do is for sortID to take priority over the null values. But the null values keep their original indice number/order unless there is a sortId that takes its place. Commented Jul 30, 2021 at 11:41
  • null - 1? the - is just a border in the row to signify another field Commented Jul 30, 2021 at 11:43
  • Your expected result has two "original array position: 4" Commented Jul 30, 2021 at 23:29

3 Answers 3

1

This does the job the way you wanted:

ngOnInit(): void {
    this.fieldsList = [...this.users];
    Array(this.fieldsList.length)
      .fill('1')
      .forEach((_, index) => {
        let user;
        let oldIndex;
        this.fieldsList.some((u, i) => {
          if(+u.sortId === index + 1) {
            user = u;
            oldIndex = i;
            return true;
          }
          return false;
        })
        const newIndex = +user?.sortId - 1;
        this.fieldsList.splice(newIndex, 0, user);
        this.fieldsList.splice(oldIndex + 1, 1);
      });
  }
Sign up to request clarification or add additional context in comments.

Comments

0

You don't want a sorting algorithm. Your sortId simply specifies the index at which to place the item in the new array. Then fill up the rest with the null values. This can be done in linear time, without any .sort().

function reorder(items) {
  const result = new Array(items.length).fill(null);
  for (const item of items)
    if (item.sortId != null)
      result[item.sortId-1] = item;
  for (let i=0, j=0; i<result.length; i++) {
    if (result[i] == null) {
      while (items[j].sortId != null) j++
      result[i] = items[j++];
    }
  }
  return result;
}

const users = [
  {
    arrayPosition: 1,
    sortId: null
  },
  {
    arrayPosition: 2,
    sortId: null
  },
  {
    arrayPosition: 3,
    sortId: null
  },
  {
    arrayPosition: 4,
    sortId: '5'
  },
  {
    arrayPosition: 5,
    sortId: null
  },
  {
    arrayPosition: 6,
    sortId: null
  },
  {
    arrayPosition: 7,
    sortId: '4'
  },
  {
    arrayPosition: 8,
    sortId: '1'
  }
];

for (const [index, user] of reorder(users).entries())
  console.log(`Row ${index+1} - Sort ID: ${user.sortId} - original array position: ${user.arrayPosition}`);

Comments

0

Here's another alternative using generators:

ngOnInit() {
  this.fieldsList = [...this.generator(this.users)];
}

*generator(users: any[]) {
  const sorted = users
    .filter(x => x.sortId)
    .sort((a, b) => +a.sortId - +b.sortId);

  let j = 0;
  for (let i = 0; i < users.length; i++) {
    if (users[i].sortId === null) {
      yield users[i];
    } else {
      yield sorted[j++];
    }
  }
}

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.