Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order array of objects based on dependencies list?

I need to order an array of objects, composed by a name and a dependencies list (made out of names).

An example of this array could be:

[
  { name: 'a', requires: ['b', 'c'] },
  { name: 'b', requires: ['c'] },
  { name: 'c', requires: [] },
]

I'd like this array to be sorted so that the items which require a specific set of dependencies will be positioned after its required dependencies.
The array could actually contain more items, I'm okay if the sorting function throws an error in case of circular dependencies.

Example output:

[
  { name: 'c', requires: [] }, // first, no dependencies, and required by both the others
  { name: 'b', requires: ['c'] }, // second, because it needs `c` first
  { name: 'a', requires: ['b', 'c'] }, // last, because requires both the others
]

What's the most concise way to do it?

like image 586
Fez Vrasta Avatar asked Apr 17 '18 10:04

Fez Vrasta


People also ask

How to sort an array of objects by the object’s properties?

Summary: in this tutorial, you will learn how to sort an array of objects by the values of the object’s properties. To sort an array of objects, you use the sort () method and provide a comparison function that determines the order of objects. Suppose that you have an array of employee objects as follows:

What is a pair of items in order of dependency?

The first item in pair is some object (item) and the second one is a collection of the same type objects that the first one depends on. I want to get a List<Item> in order of dependency, so there are not items that depend on the first element and so on (no cycled dependency!).

How to sort a list of custom objects in Java?

In the main () method, we’ve created an array list of custom objects list, initialized with 5 objects. For sorting the list with the given property, we use the list ‘s sort () method. The sort () method takes the list to be sorted (final sorted list is also the same) and a comparator.

How to sort an array of objects by age in JavaScript?

To sort an array of objects, you use the sort () method and provide a comparison function that determines the order of objects. Suppose that you have an array of employee objects as follows: The following statement snippet sorts the employees array by ages in ascending order:


2 Answers

You can try following (changed test case to support more possible combinations)

var arr = [
  { name: 'd', requires: ['a', 'c'] },
  { name: 'a', requires: ['b', 'c'] },
  { name: 'b', requires: ['c'] },
  { name: 'e', requires: ['d'] },
  { name: 'c', requires: [] },
];

var map = {}; // Creates key value pair of name and object
var result = []; // the result array
var visited = {}; // takes a note of the traversed dependency

arr.forEach(function(obj){ // build the map
  map[obj.name]  = obj;
});

arr.forEach(function(obj){ // Traverse array
  if(!visited[obj.name]) { // check for visited object
    sort_util(obj);
  }
});

// On visiting object, check for its dependencies and visit them recursively 
function sort_util(obj){
    visited[obj.name] = true;
    obj.requires.forEach(function(dep){
        if(!visited[dep]) {
           sort_util(map[dep]);
        } 
    });
    result.push(obj);
}

console.log(result);
like image 106
Nikhil Aggarwal Avatar answered Nov 04 '22 22:11

Nikhil Aggarwal


Update: thanks to Nina Scholz, I updated the code so that sort should work

This might do the job. The idea behind is, to user the sort and check if element a is in the requires of element b. If so, we can assume, that ashould be before b. But I´m not 100% sure, I just checked against your example and the example of @nikhilagw. I might have forgotten something. Please let me know if it worked!

For every element, I additionally inherit all dependencies.

const list = [
{ name: 'b', requires: ['c'] },
{ name: 'e', requires: ['d'] },
{ name: 'd', requires: ['a', 'c'] },
{ name: 'c', requires: [] },  
{ name: 'a', requires: ['b', 'c'] }, 
];

// indexed by name
const mapped = list.reduce((mem, i) => {
  mem[i.name] = i;
  return mem;
}, {});

// inherit all dependencies for a given name
const inherited = i => {
  return mapped[i].requires.reduce((mem, i) => {
  return [ ...mem, i, ...inherited(i) ];
  }, []);
}

// order ... 
const ordered = list.sort((a, b) => {
  return !!~inherited(b.name).indexOf(a.name) ? -1 : 1;
})

console.log(ordered);
like image 41
Luke Avatar answered Nov 04 '22 22:11

Luke