简体   繁体   中英

Arbitrarily reorder and sort javascript array of object literals

Good morning everyone! I'm working through a problem this morning that entails reordering the following javascript array given the requirements I've crafted below:

EDIT: I realize "reorder" and "sort" are sometimes used interchangeably. But in this context, I'm referring to 'reorder' as changing the 'order' property such that all objects have a unique order. Sorting just refers to keeping the array in ascending order based on the order property.

var toOrder = [
  {
    order: 1,
    visible: true
  },
  {
    order: 2,
    visible: true
  }
]
  1. Client code must be able to re-order this array, given a function that takes the object and a new order.

  2. Array must stay sorted in ascending order (by the order property) at all times

  3. No two objects can have the same order

I wrote some code that gets the job done, but I'm searching for a more eloquent solution. My current algorithm for reorder (in psudocode) looks like this:

reorder(myObject, newOrder);
  1. Loop over toOrder array
  2. When matched object is found:
  3. If new order is less than starting order
  4. Increment order property for objects between new order and starting order
  5. If new order is greater than starting order
  6. Decrement order property between starting order and new order
  7. If new order is the same as old order, do nothing
  8. Set new order on matched object
  9. sort()

The utility method "sort()" uses the native javascript sort() function to assure the array is ordered by the 'order' property at all times. This works fine, but is there some more efficient/eloquent solution.

Thanks in advance.

Your wording is a bit confusing, but here's how I'm interpreting it:

You have an array of objects, each with an order property. This order property must be unique. You wish to take Object A and place it in a new position, and re-apply the order properties so they are unique and sequential.

Here's how I would do it:

function reorder(object, newIndex) {

    var oldIndex = toOrder.indexOf(object);
    toOrder.splice(oldIndex, 1);
    toOrder.splice(newIndex, 0, object);

    // If you can guarantee your order properties were already indexed,
    // this loop could instead be
    // for (var i = Math.min(oldIndex, newIndex); i <= Math.max(oldIndex, newIndex); ++i)
    for (var i = 0; i < toOrder.length; ++i) {
        toOrder[i].order = i;
    }
}

Much simpler solution (still works for arbitrary order values, not only where newOrder is the actual array index):

  1. Set myObject.order to newOrder (where newOrder is some number between orders at the aim position). Eg -1 to move in front, or 1.5 to move between #1 and #2
  2. Use the custom sort()
  3. loop over the toOrder array and set the order of each item to its index (so that it becomes an integer again or is increased/decreased to match the new position)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM