2017-11-22 46 views
9

प्रिय स्टैक ओवरफ़्लो समुदाय,
मैं वस्तु संपत्ति प्रतिस्थापन (आप नीचे करने के लिए छोड़ सवाल को पढ़ने के लिए कर सकते हैं) के बारे में एक प्रश्न है। मैं एक आवेदन पर काम कर रहा हूं, जो बैक एंड से शिक्षक वस्तु प्राप्त करता है। बैक-एंड डेटाबेस की क्वेरी के लिए जावा हाइबरनेट का उपयोग कर रहा है और ऑब्जेक्ट को फ्रंट एंड (मुझे) भेजने के लिए क्रमबद्ध करता है। मुझे यह शिक्षक वस्तु मिलती है, लेकिन वस्तु में परिपत्र संदर्भ हैं। ऑब्जेक्ट के स्थान पर संदर्भ आईडी जोड़कर कौन सा जावा संभालता है। तो मुझे यह शिक्षक वस्तु मिलती है, और ऑब्जेक्ट के अंदर ये संदर्भ आईडी है कि मुझे वास्तविक वस्तु के साथ प्रतिस्थापित करने की आवश्यकता है, समस्या यह है कि वे नेस्टेड ऑब्जेक्ट्स हैं। मैं वर्तमान में जो करता हूं वह एक ढेर बनाता है, और इन आईडी और संदर्भ आईडी को खोजने के लिए वस्तुओं को पार करता है। जब मुझे एक आईडी मिलती है तो मैं इसे ढेर पर रखता हूं। कोई समस्या नहीं है, लेकिन जब मुझे संदर्भ आईडी मिलती है तो मुझे इसे स्टैक पर मिलने वाले किसी के साथ दोबारा विभाजित करने की आवश्यकता होती है। एक बार फिर यह करना मुश्किल है क्योंकि मैं इन्हें रिकर्सिव फ़ंक्शन के माध्यम से करता हूं, इसलिए मेरे पास भौतिक वस्तु नहीं है।जे एस - संपत्ति प्रतिस्थापन

मेरे सवाल है, मैं कैसे नेस्टेड वस्तु गुण

JS BIN

var stack = {}; 
var add = function(prop, data) { 
    if (prop == '@id') { 
    stack[data[prop]] = data; 
    } 
    if (prop == '@ref') { 
    // console.log(stack[data[prop]]) 
    // How do i replace the value with the stack object 
    // test.PROPERTY = stack[data[prop]] is what im looking for 
    } 
} 
var traverse = function(object) { 
    for (var property in object) { 
    if (object.hasOwnProperty(property)) { 
     add(property, object); 
     if (object[property] && typeof object[property] === 'object') { 
     traverse(object[property]); 
     } 
    } 
    } 
} 
var test = { 
    'teacher': { 
    'course': { 
     "@id": "1", 
     'students': [{ 
     "@id": "2", 
     'name': "John", 
     'course': { 
      "@ref": "1", 
     } 
     }, { 
     "@id": "2", 
     'name': "Next", 
     'course': { 
      "@ref": "1", 
     } 
     }] 
    } 
    } 
}; 
setTimeout(() => { 
    console.log(stack); 
    // console.log(test); 
}, 500); 
traverse(test); 
+0

, तुम्हारे पास क्या है और तुम क्या चाहते हो? कृपया पहले और बाद में डेटा जोड़ें। –

+0

@NinaScholz मैं वर्तमान में डेटा के साथ कुछ भी नहीं कर रहा हूं, क्योंकि मुझे यकीन नहीं है कि मैं अपने फ़ंक्शन से ऑब्जेक्ट डेटा का संदर्भ कैसे दे सकता हूं। सही बात ? – John

+1

'@ ref' एक कारण के लिए है। यदि आप वास्तविक वस्तुओं के साथ 'आईडी' को प्रतिस्थापित करने का प्रयास करते हैं, तो आप परिपत्र संदर्भों को हिट कर सकते हैं जो आपको स्मृति रिसाव तक ले जाएंगे (जिससे अधिकतम कॉल स्टैक आकार त्रुटि हो जाएगी)। –

उत्तर

3

जगह ले सकता है दो बार डेटा संरचना पर पुनरावृत्ति पर विचार करें: एक आईडी को आबाद करने के लिए

  1. रिकर्सिव ट्रेवर्सल -ऑब्जेक्ट मैप (जहां चाबियाँ आईडी हैं और मान वास्तविक वस्तुएं हैं)। आप मानचित्र को पहले रिकर्सिव कॉल में प्रारंभ कर सकते हैं, और उसके बाद इसे अगले रिकर्सन स्तर पर भेज सकते हैं।

  2. वास्तविक वस्तुओं के साथ संदर्भों को बदलने के लिए रिकर्सिव ट्रैवर्सल। चूंकि अब आपके पास नक्शा है, इसलिए यह प्रतिस्थापन जगह में किया जा सकता है।

Code

+0

मैंने इसके बारे में सोचा, लेकिन मैं अभी भी उस समस्या में भाग लेता हूं जहां मैं नहीं करता कि क्या संपत्ति है। यदि इससे समस्या हल हो जाएगी, तो कृपया एक उदाहरण पोस्ट करें क्योंकि मुझे नहीं लगता कि यह कैसे किया जा सकता है। – John

+0

बस इतना है कि मैं समझता हूं - "जॉन" और "नेक्स्ट" छात्रों की "पाठ्यक्रम" संपत्ति में "{ref:" 1 "}" ऑब्जेक्ट के बजाय आईडी "1" के साथ पाठ्यक्रम होना चाहिए? –

+0

आप सही हैं। मुझे @id: 1 के पाठ्यक्रम ऑब्जेक्ट के साथ प्रतिस्थापित करने की आवश्यकता है। जो चीज मुझे अवरुद्ध कर रही है वह वस्तुओं की गुणधर्म है। मैं नहीं देखता कि कम से कम मेरे कोड के साथ, मैं सही वस्तु के पथ को कैसे समझ सकता हूं। आपके सुझाव का एक उदाहरण महान होगा, इस बात ने मुझे स्टंप कर दिया है। – John

3

आप पहली बार वस्तु के माध्यम से पार जाना चाहिए और इकट्ठा:

  1. वस्तु शब्दकोश - वस्तु आईडी के नक्शे संदर्भ आपत्ति उठाने
  2. आइटमों की सूची है, जहां:
    • पहला तत्व
    • को प्रतिस्थापित करने के लिए संपत्ति युक्त वस्तु है
    • गुण का नाम

होने इस तरह के एक सूची समाधान की एक प्रमुख है जगह। यह आपको दोनों की अनुमति देता है: test ऑब्जेक्ट के दूसरे रिकर्सिव ट्रैवर्स से बचें, और पूरे {"@ref":"..."} ऑब्जेक्ट को प्रतिस्थापित करने के लिए पर्याप्त जानकारी संग्रहीत करें और न केवल इसकी सामग्री।

अगला, आपको सूची के माध्यम से पुन: प्रयास करना चाहिए और सभी {"@ref":"..."} ऑब्जेक्ट्स को वास्तविक वस्तुओं के संदर्भ के साथ प्रतिस्थापित करना चाहिए।

var test = { 
 
    'teacher': { 
 
     'course': { 
 
      "@id": "1", 
 
      'students': [{ 
 
       "@id": "2", 
 
       'name': "John", 
 
       'course': { 
 
        "@ref": "1", 
 
       } 
 
      }, { 
 
       "@id": "2", 
 
       'name': "Next", 
 
       'course': { 
 
        "@ref": "1", 
 
       } 
 
      }] 
 
     } 
 
    } 
 
}; 
 

 
function collectRefs(obj, dic, list) { 
 
    obj.hasOwnProperty('@id') && (dic[obj['@id']] = obj); // populate dictionary 
 
    Object.keys(obj).forEach(function(key) { 
 
     if(obj[key] && typeof obj[key] === 'object') { 
 
      if(obj[key].hasOwnProperty('@ref')) { 
 
       list.push([obj, key]) // populate list 
 
      } else { 
 
       collectRefs(obj[key], dic, list) // traverse recursively 
 
      } 
 
     } 
 
    }); 
 
    return obj; 
 
} 
 

 
function recover(obj) { 
 
    var dic = {}, list = []; 
 
    collectRefs(obj, dic, list); 
 
    list.forEach(function(item) { 
 
     item[0][item[1]] = dic[item[0][item[1]]['@ref']]; // make replacements 
 
    }); 
 
    return obj; 
 
} 
 

 
console.log(recover(test).teacher.course.students[0].course['@id']); // 1

अंत सभी {"@ref": "1"} पर आपत्ति उठाने {"@id": "1", ...}

पी.एस. संदर्भ से बदल दिया जाएगा

वैसे, वहाँ JSON प्रारूप Douglas Crockford के आविष्कारक द्वारा प्रदान की वृत्तीय संदर्भ (cycle.js) के साथ deserialize JSON क्रमानुसार करने एक बेहतर समाधान/है। यह JSONPath का उपयोग @ref वस्तुओं के मान के रूप में करता है और इसलिए संदर्भित वस्तुओं पर @id होने की आवश्यकता नहीं है। इसके अलावा, परिपत्र संदर्भों के साथ मूल ऑब्जेक्ट का पुनर्निर्माण करने के लिए अतिरिक्त डेटा संरचनाएं (जैसे उपरोक्त उदाहरण से शब्दकोश और सूची) की आवश्यकता नहीं है। इसलिए, यदि आप अपने बैक-एंड ऑब्जेक्ट को क्रमबद्ध करने के तरीके को बदल सकते हैं, तो मैं आपको इसकी जांच करने की सलाह देता हूं।

+0

अच्छा लग रहा है!लेकिन यहां अंतिम वर्ग ब्रैकेट 'आइटम [0] [आइटम [1]] = डिक [आइटम [0] [आइटम [1]] [' @ ref ']]];' अनावश्यक है, यही कारण है कि कोड स्निपेट नहीं करता है ' टी काम नहीं –

1

मैं अगर यह तुम क्या चाहते

var test = { 
 
    'teacher': { 
 
     'course': { 
 
      "@id": "1", 
 
      'students': [{ 
 
       "@id": "2", 
 
       'name': "John", 
 
       'course': { 
 
        "@ref": "1", 
 
       } 
 
      }, { 
 
       "@id": "2", 
 
       'name': "Next", 
 
       'course': { 
 
        "@ref": "1", 
 
       } 
 
      }] 
 
     } 
 
    } 
 
}; 
 

 
let tmpObj = {}; 
 
let noRef = {}; 
 

 
function traverse(obj){ 
 
    Object.keys(obj).forEach(function(v){ 
 
    if(v !== '@ref' && typeof obj[v] === 'object'){ 
 
     var newObj = obj[v]; 
 
     if(obj[v]['@id']){ 
 
     \t if(!tmpObj[v]){ 
 
     \t \t tmpObj[v] = {}; 
 
     \t } 
 
     tmpObj[v][obj[v]['@id']] = obj; 
 
     } 
 
     if(obj[v]['@ref']){ 
 
     if(tmpObj[v] && tmpObj[v][obj[v]['@ref']]){ 
 
      obj[v]['@ref'] = tmpObj[v][obj[v]['@ref']][v]; 
 
     }else{ 
 
      if(!noRef[v]){ 
 
      \t noRef[v] = []; 
 
      } 
 
      noRef[v].push(newObj) 
 
     } 
 
     } 
 
     traverse(newObj); 
 
    } 
 
\t }) 
 
} 
 

 
traverse(test); 
 
Object.keys(noRef).forEach(function(v){ 
 
\t v.forEach(function(vv){ 
 
\t \t vv['@ref'] = tmpObj[v][vv['@ref']][v]; 
 
\t }) 
 
}); 
 

 
console.log(test);

वस्तु noRef यह है मामले में रेफरी वस्तु अभी तक नहीं मिला है पता नहीं है, तो मैं उसे अपने जनक वस्तु में डाल वर्तमान रेफरी का, और जब ट्रैवर्स समाप्त हो गया है तो मैं एसोसिएटिन को

1

पर सीधे सेट करने के लिए इसे लूप करने के लिए लूप करता हूं यदि आप सीधे मूल्य निर्धारित करते हैं। अगले पुनरावृत्तियों में, ऑब्जेक्ट में एक गोलाकार संदर्भ होगा और आप अनंत लूप में समाप्त हो जाएंगे। तो इवेंट कतार में असाइनमेंट ऑपरेशन को दबाएं (ऐसा करने का एक आसान तरीका है सेटटाइमआउट 0 सेकंड पास करना)। उम्मीद है इससे आपको मदद मिलेगी।

var stack = {}; 
 
    var add = function(prop, data) { 
 
     if (prop == '@id') { 
 
     stack[data[prop]] = data; 
 
     } 
 
     if (prop == '@ref') { 
 
     // console.log(stack[data[prop]]) 
 
     // How do i replace the value with the stack object 
 
     setTimeout(function(){ 
 
      data[prop] = stack 
 
     },0); 
 
     } 
 
    } 
 
    var traverse = function(object) { 
 
     for (var property in object) { 
 
     if (object.hasOwnProperty(property)) { 
 
      add(property, object); 
 
      if (object[property] && typeof object[property] === 'object') { 
 
      traverse(object[property]); 
 
      } 
 
     } 
 
     } 
 
    } 
 
    var test = { 
 
     'teacher': { 
 
     'course': { 
 
      "@id": "1", 
 
      'students': [{ 
 
      "@id": "2", 
 
      'name': "John", 
 
      'course': { 
 
       "@ref": "1", 
 
      } 
 
      }, { 
 
      "@id": "2", 
 
      'name': "Next", 
 
      'course': { 
 
       "@ref": "1", 
 
      } 
 
      }] 
 
     } 
 
     } 
 
    }; 
 
    setTimeout(() => { 
 
     console.log(stack); 
 
     // console.log(test); 
 
    }, 500); 
 
    traverse(test);

शोर बगल में
संबंधित मुद्दे