এর আচরণ Array#sort
এবং এর তুলনাকারী স্পষ্ট করতে সহায়তা করার জন্য , প্রোগ্রামিং কোর্সের শুরুতে শেখানো এই নিষ্পাপ সন্নিবেশ সাজানোর বিষয়টি বিবেচনা করুন :
const sort = arr => {
for (let i = 1; i < arr.length; i++) {
for (let j = i; j && arr[j-1] > arr[j]; j--) {
[arr[j], arr[j-1]] = [arr[j-1], arr[j]];
}
}
};
const array = [3, 0, 4, 5, 2, 2, 2, 1, 2, 2, 0];
sort(array);
console.log("" + array);
অ্যালগরিদম উপর ফোকাস হিসাবে সন্নিবেশ সাজানোর পছন্দ উপেক্ষা হার্ডকোডেড comparator: arr[j-1] > arr[j]
। এটি আলোচনার সাথে প্রাসঙ্গিক দুটি সমস্যা রয়েছে:
>
অপারেটর অ্যারে উপাদানের কিন্তু অনেক কিছুর পেয়ারে প্রার্থনা করা হয় বস্তু জবাব দেবেন না কারণ আপনি এই ধরনের বাছাই করতে চাইতে পারেন >
একটি যুক্তিসঙ্গত উপায় (যদি আমরা ব্যবহৃত একই সত্য হতে করবে-
)।
- এমনকি যদি আপনি সংখ্যার সাথে কাজ করে থাকেন তবে প্রায়শই আপনি এখানে বর্ধিত আরোহী বাছাইয়ের চেয়ে অন্য কোনও ব্যবস্থা চান।
comparefn
আপনার সাথে পরিচিত এমন একটি যুক্তি যুক্ত করে আমরা এই সমস্যাগুলি সমাধান করতে পারি :
const sort = (arr, comparefn) => {
for (let i = 1; i < arr.length; i++) {
for (let j = i; j && comparefn(arr[j-1], arr[j]) > 0; j--) {
[arr[j], arr[j-1]] = [arr[j-1], arr[j]];
}
}
};
const array = [3, 0, 4, 5, 2, 2, 2, 1, 2, 2, 0];
sort(array, (a, b) => a - b);
console.log("" + array);
sort(array, (a, b) => b - a);
console.log("" + array);
const objArray = [{id: "c"}, {id: "a"}, {id: "d"}, {id: "b"}];
sort(objArray, (a, b) => a.id.localeCompare(b.id));
console.log(JSON.stringify(objArray, null, 2));
এখন নিষ্পাপ সাজানোর রুটিনটি সাধারণীকরণ করা হয়। আপনার উদ্বেগের প্রথম সেটটির উত্তর দিয়ে আপনি এই কলব্যাকটি কখন ডাকা হবে তা ঠিক দেখতে পাবেন:
বাছাইয়ের সময় অ্যারে সাজানো কলব্যাক ফাংশনটি কি অনেক বার বলা হয়? যদি তা হয় তবে আমি জানতে চাই যে প্রতিটি বার দুটি ফাংশনে কোন দুটি সংখ্যা পাস হবে
নীচের কোডটি চালানো থেকে বোঝা যায় যে, হ্যাঁ, ফাংশনটি অনেকবার বলা হয় এবং আপনি console.log
কোন নম্বরটি পাস হয়েছিল তা দেখতে ব্যবহার করতে পারেন:
const sort = (arr, comparefn) => {
for (let i = 1; i < arr.length; i++) {
for (let j = i; j && comparefn(arr[j-1], arr[j]) > 0; j--) {
[arr[j], arr[j-1]] = [arr[j-1], arr[j]];
}
}
};
console.log("on our version:");
const array = [3, 0, 4, 5];
sort(array, (a, b) => console.log(a, b) || (a - b));
console.log("" + array);
console.log("on the builtin:");
console.log("" +
[3, 0, 4, 5].sort((a, b) => console.log(a, b) || (a - b))
);
আপনি জিজ্ঞাসা:
তখন দুটি সেট সংখ্যার একে অপরের সাথে কীভাবে সাজানো হয়?
পরিভাষার সাথে সুনির্দিষ্ট হতে a
এবং সংখ্যার সেটb
নয় - এগুলি অ্যারেতে অবজেক্ট (আপনার উদাহরণস্বরূপ, তারা সংখ্যা)'re
সত্য কথাটি, তারা কীভাবে বাছাই করা যায় তা কার্যকর নয় কারণ এটি বাস্তবায়ন নির্ভর। আমি যদি সন্নিবেশ সাজানোর চেয়ে পৃথক বাছাই করা অ্যালগরিদম ব্যবহার করতাম, তুলনাকারীটি সম্ভবত বিভিন্ন জোড়া সংখ্যায় আহ্বান জানানো হত, তবে বাছাই কলের শেষে, জেএস প্রোগ্রামারটির সাথে সম্পর্কিত যে আক্রমণকারীটি ফলাফলটি অ্যারে অনুসারে বাছাই করা হয় তুলনাকারী, ধরে নিয়েছে যে তুলনাকারী মানগুলি প্রদান করে যা আপনার বর্ণিত চুক্তির সাথে মানিয়ে যায় (<0 কখন a < b
, 0 কখন a === b
এবং> 0 কখনa > b
)।
একই অর্থে যে যতক্ষণ আমি আমার স্পেসিফিকেশন লঙ্ঘন না করে আমার সাজানোর প্রয়োগ পরিবর্তন করার স্বাধীনতা আছে, ECMAScript এর প্রয়োগগুলি ভাষার স্পেসিফিকেশনের সীমানার মধ্যে বাছাইয়ের প্রয়োগটি চয়ন Array#sort
করতে পারে , তাই সম্ভবত বিভিন্ন তুলনামূলক কল উত্পন্ন করবে বিভিন্ন ইঞ্জিনে। এমন কোনও কোড লিখবেন না যেখানে যুক্তি তুলনার কয়েকটি নির্দিষ্ট ক্রমের উপর নির্ভর করে (না তুলনাকারীর পক্ষে প্রথম দিকে পার্শ্ব প্রতিক্রিয়া তৈরি করা উচিত)।
উদাহরণস্বরূপ, ভি 8 ইঞ্জিনটি (লেখার সময়) টিমসোর্টকে আহ্বান করে যখন অ্যারে কিছু প্রাক্পম্পিউটেড সংখ্যার চেয়ে বড় হয় এবং ছোট অ্যারে খণ্ডগুলির জন্য বাইনারি সন্নিবেশ সাজান ব্যবহার করে। যাইহোক, এটি কুইকসোর্ট ব্যবহার করত যা অস্থির এবং সম্ভবত তুলনামূলককে যুক্তি এবং কলগুলির একটি ভিন্ন ধারা দেয়।
যেহেতু বিভিন্ন ধরণের বাস্তবায়নগুলি তুলনামূলক ফাংশনের রিটার্ন মান আলাদাভাবে ব্যবহার করে, যখন তুলনাকারী চুক্তিটি মেনে চলেন না তখন এটি অবাক করা আচরণের দিকে নিয়ে যেতে পারে। উদাহরণস্বরূপ এই থ্রেডটি দেখুন ।