0

I'm trying to write a script to change the order of an array of objects, ordered by an order property to let me move an element trough the array of objects I'm working on.

If I have:

[
  {order: 0, name: 'a'},
  {order: 1, name: 'b'},
  {order: 2, name: 'c'}
]

And I want to give to b the order 0, the result of the function will be:

[
  {order: 0, name: 'b'},
  {order: 1, name: 'a'},,
  {order: 2, name: 'c'}
]

Other examples:

// a to pos 2
input = [
  {order: 0, name: 'a'},
  {order: 1, name: 'b'},
  {order: 2, name: 'c'}
]

output = [
  {order: 2, name: 'a'},
  {order: 0, name: 'b'},
  {order: 1, name: 'c'}
]

// c to pos 1
input = [
  {order: 0, name: 'a'},
  {order: 1, name: 'b'},
  {order: 2, name: 'c'}
]

output = [
  {order: 0, name: 'a'},
  {order: 1, name: 'c'},
  {order: 2, name: 'b'}
]

This is my script so far:

var movedColumn         = { order: 4, name: 'd' };
var newIndex            = 1;
var oldIndex            = movedColumn.order;
var columns             = [ { order: 0, name: 'a' }, { order: 1, name: 'b' }, { order: 2, name: 'c' }, { order: 3, name: 'd' }, { order: 4, name: 'e' }, { order: 5, name: 'f' } ];

columns.sort(function asc(a, b) { return a.order - b.order; }).forEach(function(column) {
  if (column.order >= newIndex && column.order < oldIndex) {
    column.order += 1;
  }
});
columns.find(function(column) {
  return column.name === movedColumn.name;
}).order = newIndex;

http://codepen.io/FezVrasta/pen/XXgxWe?editors=001

It works well when I want to move b to order 0, but it doesn't work well if I want to move a to order 1.
I don't care about the order of the objects in the array, in my script I order them just to "pretty print" the result and for clarity.
What matters is the value of the order properties.

How can I fix it?

short version

I need to take an object and move it in the position defined by newIndex, shifting all the elements to prevent collisions (same order on two different objects)

6
  • This makes my head hurt, why would you move b up without changing the order, and what's it supposed to be sorted by ? Commented Jan 12, 2016 at 14:17
  • 1
    You're going to have to provide more examples of starting arrays and your desired results. It's not at all clear what you're trying to do. Commented Jan 12, 2016 at 14:17
  • @Pointy I've improved the input/ouput example Commented Jan 12, 2016 at 14:19
  • @adeneo those objects will be rendered in the order defined by the order key, this is why I don't care about the order of them in the array but I care only about what order says. Commented Jan 12, 2016 at 14:20
  • I would recommend to use splice or do it manually with a for loop, and not use the sort method Commented Jan 12, 2016 at 14:28

1 Answer 1

1

Probably this is a solution:

var movedColumn         = { order: 5, name: 'f' };
var newIndex            = 4;
var oldIndex            = movedColumn.order;
var columns             = [ { order: 0, name: 'a' }, { order: 1, name: 'b' }, { order: 2, name: 'c' }, { order: 3, name: 'd' }, { order: 4, name: 'e' }, { order: 5, name: 'f' } ];

columns.sort(function asc(a, b) { return a.order - b.order; }).forEach(function(column) {
  if (newIndex < oldIndex) {
    if (column.order >= newIndex && column.order < oldIndex) {
      column.order += 1;
    }
  }
  if (newIndex > oldIndex) {
    if (column.order > oldIndex && column.order <= newIndex) {
      column.order -= 1;
    }
  }
});
columns.find(function(column) {
  return column.name === movedColumn.name;
}).order = newIndex;

It seems to work in both the directions, it's not nice to see but it does the job.

Logically it will do nothing if you try to move the element to its very same order.

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

3 Comments

Shouldn't that be column.order > oldIndex && column.order <= newIndex?
It works in the way I've posted. You can try it here let me know if there's something wrong please.
Yes, it really doesn't work when you move something upwards by more than 1 (example). Please test instead of only trying :-)

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.