4

에 순환 참조를 감지하는 방법 :예를 들어 자바 스크립트

$ node 
> var x = {} 
undefined 
> x.x = x 
{ x: [Circular] } 

구조의 종류들이 이러한 목표를 달성하는 데 사용하는 궁금, 그것은 내가 방금 무슨 짓을했는지에 직접 인코딩되지 있기 때문에. 그들은 같은 것을 할 것 같아 :

var graph = new Graph(object) 
graph.detectCircularReferences() 

을 그리고 그것은 그들을 얻을 것입니다,하지만 어떻게 작동하는지 확실하지. 그것을 구현하는 방법을 배우기를 원합니다.

+2

[직접 그래프의 사이클을 감지하는 데 가장 적합한 알고리즘] (https://stackoverflow.com/questions/261573/best-algorithm-for-detecting-cycles-in-a-directed-graph)) –

+0

[여기] (https://github.com/nodejs/node/blob/3fe165ace6723b1446994574a5197bb70d9a6c72/lib/util.js#L186) 및 [여기] (https://github.com/nodejs/node/blob/)를 참조하십시오. 3fe165ace6723b1446994574a5197bb70d9a6c72/lib/util.js # L168). 그것들은 기본적으로 순환 객체를 JSON.string 화하려고 시도 할 때 예외가 발생합니다. –

+0

발생하는 객체의 참조를 배열로 푸시하는 재귀 함수를 가질 수 있으며 각 객체에 대해 참조가 이미 발생했는지 검사합니다 배열에서) 또는 아닙니다. –

답변

0

의견을 통해이 아이디어를 얻었습니다. 전달 된 객체를 배열과 객체 위에 가로 지르고 순환 참조를 가리키는 경로 배열을 반환합니다.

// This function is going to return an array of paths 
 
// that point to the cycles in the object 
 
const getCycles = object => { 
 
    if (!object) { 
 
     return; 
 
    } 
 

 
    // Save traversed references here 
 
    const traversedProps = new Set(); 
 
    const cycles = []; 
 

 
    // Recursive function to go over objects/arrays 
 
    const traverse = function (currentObj, path) { 
 
     // If we saw a node it's a cycle, no need to travers it's entries 
 
     if (traversedProps.has(currentObj)) { 
 
      cycles.push(path); 
 
      return; 
 
     } 
 

 
     traversedProps.add(currentObj); 
 

 
     // Traversing the entries 
 
     for (let key in currentObj) { 
 
      const value = currentObj[key]; 
 
      // We don't want to care about the falsy values 
 
      // Only objects and arrays can produce the cycles and they are truthy 
 
      if (currentObj.hasOwnProperty(key) && value) { 
 
       if (value.constructor === Object) { 
 
        // We'd like to save path as parent[0] in case when parent obj is an array 
 
        // and parent.prop in case it's an object 
 
        let parentIsArray = currentObj.constructor === Array; 
 
        traverse(value, parentIsArray ? `${path}[${key}]` : `${path}.${key}`); 
 

 
       } else if (value.constructor === Array) { 
 
        for (let i = 0; i < value.length; i += 1) { 
 
         traverse(value[i], `${path}.${key}[${i}]`); 
 
        } 
 
       } 
 

 
       // We don't care of any other values except Arrays and objects. 
 
      } 
 
     } 
 
    } 
 

 
    traverse(object, 'root'); 
 
    return cycles; 
 
};

그럼 당신은 이런 식으로 테스트 할 수 있습니다 :

// Making some cycles. 
 
const x = {}; 
 
x.cycle = x; 
 
const objWithCycles = { 
 
    prop: {}, 
 
    prop2: [1, 2, [{subArray: x}]] 
 
}; 
 
objWithCycles.prop.self = objWithCycles; 
 

 
console.log(getCycles(objWithCycles));

그것은 개체 사이클의 목록입니다 다음과 같은 출력이 생성

[ 'root.prop.self', 'root.prop2[2][0].subArray.cycle' ]