0

I have an array of objects like this and would like to re-order with another array of objects. I have tried using indexOf but am possible confusing my syntax as the array fails to re-order. I have read similar threas but haven't been able to apply those solutions to my problem. Here is code:

    const task = [
       {'title':1.1 , 'description': 'task description here' },
       {'title':1.2 , 'description': 'task description here' },
       {'title':1.3 , 'description': 'task description here' },
       {'title':1.4 , 'description': 'task description here' }
    ];

    var taskSort = [
            {'title':1.2 },
            {'title':1.4 },
            {'title':1.3 },
            {'title':1.1 }
        ];

    task.sort(function(a, b) {
      return taskSort.indexOf(a.title) - taskSort.indexOf(b.title); \\have tried many variations of this line
    });
    console.clear();
    console.log(task);

Many thanks in advance!

Dave
  • 15
  • 3
  • How do you want them to be sorted? What is the condition? – Konrud Dec 04 '19 at 14:34
  • Does this answer your question? [Sort array of objects by string property value](https://stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value) – dw_ Dec 04 '19 at 14:35
  • Does this answer your question? [How do I sort an array of objects based on the ordering of another array?](https://stackoverflow.com/questions/9755889/how-do-i-sort-an-array-of-objects-based-on-the-ordering-of-another-array) – Heretic Monkey Dec 04 '19 at 14:37
  • You're searching for an element that doesn't exist in the `taskSort`. Try doing `taskSort.map(o => o.title).index(a.title)` and that would return the correct index. Well of course save `taskSort.map(o => o.title)` in a variable so that you're not doing `map` op again and again. – Rahul Sharma Dec 04 '19 at 14:42

4 Answers4

1

Basically, you aren't sorting the values, but rearranging them based on the order specified in another array

Hence, you cannot use the Array.prototype.sort logic, but can do the following

var taskSort = [
            {'title':1.2 },
            {'title':1.4 },
            {'title':1.3 },
            {'title':1.1 }
        ];
   var task = [
       {'title':1.1 , 'description': 'task description here' },
       {'title':1.2 , 'description': 'task description here' },
       {'title':1.3 , 'description': 'task description here' },
       {'title':1.4 , 'description': 'task description here' }
    ];
   var sortedTask = taskSort.map(tS => task.find(t => t.title === tS.title))

console.log(sortedTask);

Essentially, you are mapping through the taskSort array and creating a new array, where the value is satisfying the condition marked by the value in the taskSort array

Dhananjai Pai
  • 5,914
  • 1
  • 10
  • 25
1

You could build an object with the wanted order of title and take the delta of the values for sorting.

By taking this approach, you could add value as default, if a title value is not know. Then you could move this items to bottom with Number.MAX_VALUE or to top with -Number.MAX_VALUE, like

(order[a] || -Number.MAX_VALUE) - (order[b] || -Number.MAX_VALUE) //   top 
(order[a] || Number.MAX_VALUE) - (order[b] || Number.MAX_VALUE)  // bottom

 var task = [{ title: 1.1, description: 'task description here' }, { title: 1.2, description: 'task description here' }, { title: 1.3, description: 'task description here' }, { title: 1.4, description: 'task description here' }];
    taskSort = [ { title: 1.2 }, { title: 1.4 }, { title: 1.3 }, { title: 1.1 }],
    order = Object.fromEntries(taskSort.map(({ title }, i) => [title, i + 1]));

task.sort(({ title: a }, { title: b }) => order[a] - order[b]);

console.log(task);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

You're not getting the expected outcome because you're checking the index of an int (a.title) in an object array (taskSort). So since there are no elements such as that, taskSort.indexOf(a.title) always returns -1. The easiest way would be to modify the task sort like that:

var taskSort = [1.2, 1.4, 1.3, 1.1];

And everything should work as expected.

Maciej B. Nowak
  • 1,180
  • 7
  • 19
0

Your implementation is actually very close, I think you just need to use findIndex instead of indexOf like:

return taskSort.findIndex(element => element.title === a.title) - taskSort.findIndex(element => element.title === b.title);

indexOf tries to match your input with an exact element of the array, not with a property of an element.

volcanic
  • 312
  • 1
  • 6