-1

I have an array of Javascript objects as follows

a=[
  {id:1, parentId:2},
  {id:2, parentId:3},
  {id:3, parentId:4},
  {id:4, parentId:1},
  {id:5, parentId:5}
];

I would like to detect in this array if any object refers to itself directly (5->5) or if refers to itself by other parents like 1->2->3->4->1

what is the best way to write it?

PS. There is another question like this one but it is not answered the question. the accepted answer is about a graph and it returns color coding, How to detect a loop in a hierarchy of javascript elements but mine is parentId

my expected behaviour is: false, 5->5 and 1->2->3->4->1 or simply false, neighter colour coding nor for graph :)

Mehran Ishanian
  • 369
  • 2
  • 4
  • 13
  • Why does it make a difference whether it's `parent` or `parentId`? The algorithm is the same. – Barmar Aug 16 '22 at 17:20
  • Dear @Barmar thanks for your answer. The accepted answer is a graph with vortex graph = [ [2, 1], [3, 2], [1300023, 3], [1, 1300023], ]; and it is not an array of objects. and return some colour coding array, I would like just to know if it is false or which id is incorrect – Mehran Ishanian Aug 16 '22 at 17:42
  • If this is homework, see: [How to ask homework question](https://meta.stackoverflow.com/questions/334822/how-do-i-ask-and-answer-homework-questions) and [Open letter to students with homework problems](https://softwareengineering.meta.stackexchange.com/questions/6166/open-letter-to-students-with-homework-problems) – Barmar Aug 16 '22 at 17:49
  • Sorry, @Barmar if it looks like homework to you. anyway thanks for your answer – Mehran Ishanian Aug 16 '22 at 17:51

2 Answers2

1

Your data does describe a [directed] graph. In fact, your model is for all intents and purposes an adjacency list describing this :

enter image description here

Any graph traversal algorithm that tracks visited nodes can detect cycles in the graph:

I might suggest converting your list of {id, parentId} tuples into a map, where the keys are the id properties, and the value is the associated parentId (or a list of associated parentID properties, in case the same node can have has multiple parents).

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
1

This one is non-recursive. Not most efficient, but checks items one by one - looking up the parent chain until found a match or no parent found. Then moving to next item.

Edit: Need of course to check against all items along the way of the chain (not just first) to prevent infinite loops in case of (1->2->2).

var a = [
  {id:1, parentId:2},
  {id:2, parentId:2},
  {id:3, parentId:4},
  {id:4, parentId:7},
  {id:5, parentId:6}
];

function search_id(arr, id) {
  return arr.find(item => item.id === id)
}

function is_array_cyclic(arr) {
  for (var i = 0; i < arr.length; i++) {
    var item = arr[i];
    var seen = [item.id]

    while (true) {
      var parent = search_id(arr, item.parentId);
      if (parent === undefined) {
        break;
      }
      if (seen.indexOf(parent.id)>-1) {
        // cyclical
        return true;
      }
      seen.push(parent.id);
      item = parent;
    }
  }
  return false;
}

console.log(is_array_cyclic(a))
IT goldman
  • 14,885
  • 2
  • 14
  • 28