আমি অনুমান করি যে একটি উপাদান দেওয়া হয়েছে যেখানে তার সমস্ত শিশুদের নথিতে ক্রমানুসারে আদেশ দেওয়া হয়েছে, উপাদানগুলির নথির অবস্থানের তুলনা করে বাইনারি অনুসন্ধান করা দ্রুততম উপায় হতে হবে। যাইহোক, উপসংহারে যেমন উপস্থাপন করা হয়েছিল তেমন অনুমানকে প্রত্যাখ্যান করা হয়। আপনার যত বেশি উপাদান রয়েছে, পারফরম্যান্সের সম্ভাবনা তত বেশি। উদাহরণস্বরূপ, যদি আপনার 256 টি উপাদান থাকে, তবে (সর্বোত্তমভাবে) আপনার কেবলমাত্র তাদের 16 টি পরীক্ষা করতে হবে! 65536 এর জন্য, কেবল 256! পারফরম্যান্স বেড়ে যায় 2 শক্তি! আরও সংখ্যা / পরিসংখ্যান দেখুন। পরিদর্শন উইকিপিডিয়া
(function(constructor){
'use strict';
Object.defineProperty(constructor.prototype, 'parentIndex', {
get: function() {
var searchParent = this.parentElement;
if (!searchParent) return -1;
var searchArray = searchParent.children,
thisOffset = this.offsetTop,
stop = searchArray.length,
p = 0,
delta = 0;
while (searchArray[p] !== this) {
if (searchArray[p] > this)
stop = p + 1, p -= delta;
delta = (stop - p) >>> 1;
p += delta;
}
return p;
}
});
})(window.Element || Node);
তারপরে, আপনি যেভাবে এটি ব্যবহার করছেন তা হ'ল যে কোনও উপাদানটির 'প্যারেন্ট ইন্ডেক্স' সম্পত্তি পেয়ে। উদাহরণস্বরূপ, নিম্নলিখিত ডেমো পরীক্ষা করে দেখুন।
(function(constructor){
'use strict';
Object.defineProperty(constructor.prototype, 'parentIndex', {
get: function() {
var searchParent = this.parentNode;
if (searchParent === null) return -1;
var childElements = searchParent.children,
lo = -1, mi, hi = childElements.length;
while (1 + lo !== hi) {
mi = (hi + lo) >> 1;
if (!(this.compareDocumentPosition(childElements[mi]) & 0x2)) {
hi = mi;
continue;
}
lo = mi;
}
return childElements[hi] === this ? hi : -1;
}
});
})(window.Element || Node);
output.textContent = document.body.parentIndex;
output2.textContent = document.documentElement.parentIndex;
Body parentIndex is <b id="output"></b><br />
documentElements parentIndex is <b id="output2"></b>
সীমাবদ্ধতা
- সমাধানটির এই বাস্তবায়ন আইই 8 এবং নীচে কাজ করবে না।
বাইনারি ভিএস লিনিয়ার অনুসন্ধান 200 হাজার উপাদানগুলিতে (কিছু মোবাইল ব্রাউজার ক্র্যাশ হতে পারে, সাবধান!):
- এই পরীক্ষায় আমরা দেখতে পাচ্ছি যে মধ্যবর্তী উপাদান ভিএসকে বাইনারি অনুসন্ধান করতে লিনিয়ার অনুসন্ধানের জন্য কতক্ষণ সময় লাগে। কেন মাঝারি উপাদান? কারণ এটি অন্যান্য সমস্ত অবস্থানের গড় অবস্থানে রয়েছে, সুতরাং এটি সম্ভাব্য সমস্ত অবস্থানের সেরা উপস্থাপন করে।
বাইনারি অনুসন্ধান
(function(constructor){
'use strict';
Object.defineProperty(constructor.prototype, 'parentIndexBinarySearch', {
get: function() {
var searchParent = this.parentNode;
if (searchParent === null) return -1;
var childElements = searchParent.children,
lo = -1, mi, hi = childElements.length;
while (1 + lo !== hi) {
mi = (hi + lo) >> 1;
if (!(this.compareDocumentPosition(childElements[mi]) & 0x2)) {
hi = mi;
continue;
}
lo = mi;
}
return childElements[hi] === this ? hi : -1;
}
});
})(window.Element || Node);
test.innerHTML = '<div> </div> '.repeat(200e+3);
// give it some time to think:
requestAnimationFrame(function(){
var child=test.children.item(99.9e+3);
var start=performance.now(), end=Math.round(Math.random());
for (var i=200 + end; i-- !== end; )
console.assert( test.children.item(
Math.round(99.9e+3+i+Math.random())).parentIndexBinarySearch );
var end=performance.now();
setTimeout(function(){
output.textContent = 'It took the binary search ' + ((end-start)*10).toFixed(2) + 'ms to find the 999 thousandth to 101 thousandth children in an element with 200 thousand children.';
test.remove();
test = null; // free up reference
}, 125);
}, 125);
<output id=output> </output><br />
<div id=test style=visibility:hidden;white-space:pre></div>
পিছনের দিকে (`lastIndexOf`) লিনিয়ার অনুসন্ধান
(function(t){"use strict";var e=Array.prototype.lastIndexOf;Object.defineProperty(t.prototype,"parentIndexLinearSearch",{get:function(){return e.call(t,this)}})})(window.Element||Node);
test.innerHTML = '<div> </div> '.repeat(200e+3);
// give it some time to think:
requestAnimationFrame(function(){
var child=test.children.item(99e+3);
var start=performance.now(), end=Math.round(Math.random());
for (var i=2000 + end; i-- !== end; )
console.assert( test.children.item(
Math.round(99e+3+i+Math.random())).parentIndexLinearSearch );
var end=performance.now();
setTimeout(function(){
output.textContent = 'It took the backwards linear search ' + (end-start).toFixed(2) + 'ms to find the 999 thousandth to 101 thousandth children in an element with 200 thousand children.';
test.remove();
test = null; // free up reference
}, 125);
});
<output id=output> </output><br />
<div id=test style=visibility:hidden;white-space:pre></div>
সামনের দিকে (`indexOf`) লিনিয়ার সন্ধান
(function(t){"use strict";var e=Array.prototype.indexOf;Object.defineProperty(t.prototype,"parentIndexLinearSearch",{get:function(){return e.call(t,this)}})})(window.Element||Node);
test.innerHTML = '<div> </div> '.repeat(200e+3);
// give it some time to think:
requestAnimationFrame(function(){
var child=test.children.item(99e+3);
var start=performance.now(), end=Math.round(Math.random());
for (var i=2000 + end; i-- !== end; )
console.assert( test.children.item(
Math.round(99e+3+i+Math.random())).parentIndexLinearSearch );
var end=performance.now();
setTimeout(function(){
output.textContent = 'It took the forwards linear search ' + (end-start).toFixed(2) + 'ms to find the 999 thousandth to 101 thousandth children in an element with 200 thousand children.';
test.remove();
test = null; // free up reference
}, 125);
});
<output id=output> </output><br />
<div id=test style=visibility:hidden;white-space:pre></div>
পূর্ববর্তী উপাদানসিবলিং কাউন্টার অনুসন্ধান
প্যারেন্ট ইনডেক্স পেতে পূর্ববর্তী উপাদান সংখ্যার সংখ্যা গণনা করে।
(function(constructor){
'use strict';
Object.defineProperty(constructor.prototype, 'parentIndexSiblingSearch', {
get: function() {
var i = 0, cur = this;
do {
cur = cur.previousElementSibling;
++i;
} while (cur !== null)
return i; //Returns 3
}
});
})(window.Element || Node);
test.innerHTML = '<div> </div> '.repeat(200e+3);
// give it some time to think:
requestAnimationFrame(function(){
var child=test.children.item(99.95e+3);
var start=performance.now(), end=Math.round(Math.random());
for (var i=100 + end; i-- !== end; )
console.assert( test.children.item(
Math.round(99.95e+3+i+Math.random())).parentIndexSiblingSearch );
var end=performance.now();
setTimeout(function(){
output.textContent = 'It took the PreviousElementSibling search ' + ((end-start)*20).toFixed(2) + 'ms to find the 999 thousandth to 101 thousandth children in an element with 200 thousand children.';
test.remove();
test = null; // free up reference
}, 125);
});
<output id=output> </output><br />
<div id=test style=visibility:hidden;white-space:pre></div>
কোন অনুসন্ধান
ব্রাউজারটি অনুসন্ধানটি অপ্টিমাইজ করে দিলে পরীক্ষার ফলাফল কী হবে তা বেঞ্চমার্কিংয়ের জন্য।
test.innerHTML = '<div> </div> '.repeat(200e+3);
// give it some time to think:
requestAnimationFrame(function(){
var start=performance.now(), end=Math.round(Math.random());
for (var i=2000 + end; i-- !== end; )
console.assert( true );
var end=performance.now();
setTimeout(function(){
output.textContent = 'It took the no search ' + (end-start).toFixed(2) + 'ms to find the 999 thousandth to 101 thousandth children in an element with 200 thousand children.';
test.remove();
test = null; // free up reference
}, 125);
});
<output id=output> </output><br />
<div id=test style=visibility:hidden></div>
কনকুলশন
তবে, ক্রোমে ফলাফলগুলি দেখার পরে, ফলাফলগুলি প্রত্যাশিত বিপরীত। ডাম্বার ফরোয়ার্ড লিনিয়ার অনুসন্ধান বাইনারি অনুসন্ধানের চেয়ে দ্রুত 187 এমএস, 3850% ছিল। স্পষ্টতই, ক্রোম কোনওভাবে যাদুকরীভাবে আউটসামার্ট করেছিল console.assert
এবং এটিকে অপ্টিমাইজ করেছে, বা (আরও আশাবাদী) ক্রোম অভ্যন্তরীণভাবে ডিওমের জন্য সংখ্যাসূচক ইনডেক্সিং সিস্টেম ব্যবহার করে এবং কোনও অভ্যন্তরীণ ক্ষেত্রে Array.prototype.indexOf
ব্যবহার করার সময় প্রয়োগ করা অপ্টিমাইজেশনের মাধ্যমে এই অভ্যন্তরীণ সূচক সিস্টেমটি উদ্ভাসিত হয় HTMLCollection
।
parent.childNodes
পরিবর্তে আপনার কী করার দরকার নেইparent.children
? অপেক্ষাকৃত পরবর্তীটি শুধু তালিকাElements
, বিশেষ ব্যতীতText
নোড ... উত্তর এখানে যেমন ব্যবহারের কিছুpreviousSibling
, সব সন্তানের নোড ব্যবহার করে, ভিত্তি করে যেহেতু অন্যদের শুধুমাত্র শিশুদের যা সঙ্গে মাথা ঘামায়Element
গুলি ... (!)