0

I have an application that has an array (selectedTiles). Each Tile in the array has 2 properties that dictate the location of that tile on the page layout (Col(umn) and Row).

link to plunkr

<div gridster>
    <ul>
        <li gridster-item="item" ng-repeat="tile in selectedTiles"></li>
    </ul>
</div>

Problem Behavior: When I move a tile (Ex: say swap two tiles), the 'tile.col' and 'tile.row' properties change its values for each tile to correspond to the new grid position. However the order of the indexed array stays the same. This makes the keyboard navigation unordered if it were moving to the next tile by the next index position.

*Goal Behavior Therefore, I need to create a new array that pushes each tile in SelectedTiles into a new array that takes the tile.col and tile.row properties and sorts them, like so:

$scope.selectedTiles = [
  { row: 0, col: 0 },
  { row: 0, col: 1 },
  { row: 0, col: 2 },
  { row: 0, col: 3 }.
  { row: 1, col: 0 },
  { row: 1, col: 1 },
  { row: 1, col: 2 },
  { row: 1, col: 3 },
  { row: 2, col: 0 },
  { row: 2, col: 1 },
  { row: 2, col: 2 },
  { row: 2, col: 3 }
];

That way the index order follows a pattern of having the top-most left tile as the index[0] and bottom-most right tile as the last index in the array everytime a tile is moved.

I haven no idea how to do this

Kode_12
  • 4,506
  • 11
  • 47
  • 97

2 Answers2

0

If I understood your question correctly, you trying to sort the array based on row/col values after those have been changed. Below is one way to do it. I've added the id property to each element just to make what will happen obvious.

function compare(a, b) {
  if (a.row < b.row) {
    return -1;
  } else if (a.row > b.row) {
    return 1;
  } else {
    if (a.col < b.col) {
      return -1;
    } else if (a.col > b.col) {
      return 1;
    } else {
      return 0;
    }
  }
}

var newItems = items.sort(compare);

console.log(JSON.stringify(newItems));

Let's say some row/col values have been changed, then it will sort this:

var items = [
      { row: 2, col: 3, id: 1 },
      { row: 0, col: 1, id: 2 },
      { row: 0, col: 2, id: 3 },
      { row: 0, col: 3, id: 4 },
      { row: 1, col: 0, id: 5 },
      { row: 1, col: 1, id: 6 },
      { row: 1, col: 2, id: 7 },
      { row: 1, col: 3, id: 8 },
      { row: 2, col: 2, id: 9 },
      { row: 2, col: 1, id: 10 },
      { row: 2, col: 0, id: 11 },
      { row: 0, col: 0, id: 12 }
      ];

Into the following (you can then copy it back to whatever structure you need to reflect it on the screen) :

[
{"row":0,"col":0,"id":12},
{"row":0,"col":1,"id":2},
{"row":0,"col":2,"id":3},
{"row":0,"col":3,"id":4}, 
{"row":1,"col":0,"id":5},
{"row":1,"col":1,"id":6},
{"row":1,"col":2,"id":7},
{"row":1,"col":3,"id":8},
{"row":2,"col":0,"id":11},
{"row":2,"col":1,"id":10},
{"row":2,"col":2,"id":9},
{"row":2,"col":3,"id":1}
]
  • https://plnkr.co/edit/Kqv44Kh6uVlcrS1j5mgQ (This is just the sorting. Look at the script.js file) – Nikolai Efimov Jun 02 '16 at 01:35
  • thank you, i've having toruble understanding the compare function you have written. What is a and b in the parameters, and what does the return value signify? – Kode_12 Jun 02 '16 at 02:02
  • "a" and "b" are automatically assigned/passed in and are "next" two values in the array. That's how you can access elements of an array in the sort function. It's a built in mechanism of most languages. – Nikolai Efimov Jul 13 '16 at 23:54
0

Here's a nice function to sort arrays of objects by multiple properties, both ascending or descending. An example is in the function's doc string.

function dynamicSort(property) {
  var sortOrder = 1;
  if(property[0] === "-") {
    sortOrder = -1;
    property = property.substr(1);
  }
  return function (a,b) {
    var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
    return result * sortOrder;
  }
} // dynamicSort()

function dynamicSortMultiple() {
  /*
   * save the arguments object as it will be overwritten
   * note that arguments object is an array-like object
   * consisting of the names of the properties to sort BY
   *
   * Example:
   *
   * var People = [
   *   {Name: "Name", Surname: "RRR"},
   *   {Name: "AAA",  Surname: "ZZZ"},
   *   {Name: "Name", Surname: "AAA"},
   *   {Name: "Name", Surname: "MPF"},
   *   {Name: "AAA",  Surname: "YYY"}
   * ];
   * People.sort(dynamicSort("Surname"));
   * People.sort(dynamicSortMultiple("Name", "-Surname"));
   */
  var props = arguments;
  return function (obj1, obj2) {
    var i = 0, result = 0, numberOfProperties = props.length;
    /* try getting a different result from 0 (equal)
     * as long as we have extra properties to compare
     */
    while(result === 0 && i < numberOfProperties) {
      result = dynamicSort(props[i])(obj1, obj2);
      i++;
    }
    return result;
  }
} // dynamicSortMultiple()

Original post: Sort array of objects by string property value in JavaScript

Community
  • 1
  • 1
Mike Scotty
  • 10,530
  • 5
  • 38
  • 50
  • This is confusing to follow I don't know how to plug in my object array to match where they would be inserted with the example you have provided – Kode_12 Jun 02 '16 at 21:25
  • You don't "plug it in", you just use it: `$scope.selectedTiles.sort(dynamicSortMultiple("row", "col"));` - you can use these functions with any array. Just call `myArray.sort( ... )` as shown in the example above with the `People` array. – Mike Scotty Jun 02 '16 at 21:28