Skip to content

Latest commit

 

History

History
95 lines (65 loc) · 8.83 KB

Arrays Sort Method Quirks and Functionality.hy.md

File metadata and controls

95 lines (65 loc) · 8.83 KB

Ի՞նչպես կատարել զանգվածի տեսակավորում՝ (sorting) օգտագործելով ներդրված sort մեթոդը։ Ի՞նչու երբ տեսակավորում ենք թվերի զանգված, արդյունքը կարող է մեզ անակնկալի բերել, և ի՞նչպես կարող ենք որպես արգումենտ փոխանցվող ֆունկցիայի օգնությամբ ստանալ ճիշտ տեսակավորված թվերի զանգված։ Ի՞նչպես ստանալ էլեմենտների պատահական դասավորվածությամբ զանգված։

JavaScript-ում զանգվածների տեսակավորումը կատարվում է array.sort մեթոդի օգնությամբ։ Այս մեթոդի աշխատանքի սկզբունքները շատերը հաճախ չեն պատկերացնում այնպես, ինչպես հարկն է։ Մեթոդի ներքին իրականացումը հիմնականում արագ տեսակավորման ալգորիթմի օգնությամբ է (QuickSort Algorithm), իսկ սկզբնապես տեսակավորումը կատարվում է ըստ լեքսիկոգրաֆիկ (բառարանագրային) հերթականության։ Պարզ ասած՝ ըստ այբենական հերթականության, միայն այն տարբերությամբ, որ ցանկացած մեծատառ փոքր է նույն այբուբենին պատկանող ցանկացած փոքրատառից։

Պետք է նշել, որ sort մեթոդը ՓՈԽՈՒՄ է զանգվածը, որի վրա կանչվել է, և նոր վերադարձնում է տեսակավորված զանգված։ Սա մեթոդի կարևոր առանձնահատկություն է, որն անհրաժեշտ է հիշել։ Կատարել զանգվածի տեսակավորում՝ շատ հեշտ է, ուղղակի զանգվածի վրա կանչում ենք մեթոդը՝ առանց լրացուցիչ պարամետրերի։ Իսկ թե ե՞րբ է անհաժեշտ մեթոդին արգումենտ տալ, դեռևս կանդրադառնամ:

Բերեմ պարզ օրինակ՝

let arr = ["Hasmik", "Armen", "Nelly"];
arr.sort();
console.log(arr); // ["Armen", "Hasmik", "Nelly"]

Մենք զանգվածը տեսակավորեցինք ըստ աճման կարգի, "H" տառը հաջորդում է "A" տառին, իսկ "N""H"-ին։ Եթե մեզ պետք է տեսակավորել ըստ նվազման կարգի, այդ դեպքում անհրաժեշտ կլինի sort մեթոդից հետո անմիջապես օգտագործել նաև reverse մեթոդը․

arr.sort().reverse();
console.log(arr); // ["Nelly", "Hasmik", "Armen"]

Իսկ հիմա եթե մեթոդն օգտագործենք թվերի զանգվածի վրա, մենք կստանանք ոչ այն, ինչ հավանաբար ուզում էինք

let numArray = [7, 50, 300];
numArray.sort();
console.log(numArray); // [300, 50, 7] Oops!

Մեթոդը թվերի տեսակավորումը փաստացի կատարում է այնպես, ինչպես տողերինը։ Սկզբից համեմատում է առաջին սիմվոլները, եթե առաջին թվի առաջին սիմվոլը փոքր է երկրորդ թվի առաջին սիմվոլից, ապա համարում է որ առաջին թիվը փոքր է երկրորդ թվից և համեմատությունն այլևս չի շարունակում։ Մեր օրինակում երբ համեմատում է 7-ն ու 50-ը, սկզբից վերցնում է նախ առաջին սիմվոլները, "7" > "5", այլևս չի շարունակում համեմատել, և համարում է որ 7-ը 50-ից մեծ է, ու ըստ այդմ էլ տեսակավորում է:

Դիմենք մեր սիրելի MDN-ի օգնությանը, որպեսզի հասկանանք թե ինչ կարելի է անել այս իրավիճակում: Նախ այնտեղ կարդում ենք, որ տեսակավորումը default կատարվում է ըստ Unicode-ում տվյալ սիմվոլի կոդի համարների հերթականության։ Հետո նկատում ենք, որ մեթոդի գրելաձևը ենթադրում է նաև ոչ պարտադիր պարամետրի առկայություն։

arr.sort([compareFunction])

  • compareFunction - Ոչ պարտադիր պարամետր է։ Իրենից ներկայացնում է հետադարձ կանչի ֆունկցիա, որը սահմանում է թե ինչ օրինաչափությամբ պետք է կատարվի զանգվածի տեսակավորումը։ Եթե բացակայում է, ապա զանգվածի էլեմենտը անուղղակիորեն վերափոխվում է String տիպի, և տեսակավորումը կատարվում է ըստ Unicode-ում տվյալ սիմվոլի դիրքի։

Որպեսզի թվային զանգվածում կատարենք ճիշտ տեսակավորում՝ մեզ անհրաժեշտ է մեթոդին որպես արգումենտ տալ հետևյալ հետադարձ կանչի ֆունկցիան՝

function(a, b) {return a - b}

Այս ֆունկցիան հաղորդելով որպես արգումենտ՝ մենք հնարավորություն ենք տալիս sort մեթոդին 2 էլեմենտների պարզագույն համեմատություն անել և գտնել թե որն է որից մեծ։ Եթե հետադարձ կանչի ֆունկցիայի վերադարձրած արժեքը լինում է բացասական, ապա մեթոդը հասկանում է, որ երկրորդ թիվը մեծ է առաջինից, հերթականությունը ճիշտ է, և ոչ մի բան անելու հարկ չկա։ Երբ հետադարձ կանչի ֆունկցիան վերադարձնում է 0, ապա մեթոդը հասկանում է, որ թվերը հավասար են իրար, և կրկին ոչ մի բան պետք չի անել։ Իսկ այ երբ հետադարձ կանչի ֆունկցիան վերադարձնում է դրական թիվ՝ դա բնականաբար հնարավոր է միայն այն դեպքում, երբ առաջին թիվը մեծ է երկրորդ թվից, հետևաբար հերթականությունը ճիշտ չէ, և մեթոդը տեղերով փոխում է թվերին։

Հիմա փորձենք մեր վերևի օրինակի զանգվածի վրա կանչել sort մեթոդը՝ որպես արգումենտ նրան տալով վերը նկարագրված հետադարձ կանչի ֆունկցիան։

numArray.sort(function (a, b) {
  return a - b;
});

Կստանանք [7, 40, 300], ինչը և ուզում էինք։

Եվս մի նկատառում՝ երբեմն մեզ անհրաժեշտ է ստանալ տեսակավորված զանգված, սակայն ոչ թե աճման՝ այլ նվազման կարգով։ Ի՞նչպես անել։ Դա շատ հեշտ է, ընդամենը պետք է որպես արգումենտ հաղորդվող հետադարձ կապի ֆունկցիայի մարմնում վերադարձնել ոչ թե a - b, այլ b - a: Փորձենք․

numArray.sort(function (a, b) {
  return b - a;
});

Կստանանք [300, 40, 7], այն ինչ ակնկալում էինք։

Կոդը կարելի է դարձնել ավելի կարճ և գեղեցիկ, եթե հետադարձ կապի ֆունկցիան գրենք՝ օգտագործելով ES6arrow function նոտացիան։ Օրինակ աճման կարգով տեսակավորելու դեպքում ՝

numAarray.sort((a, b) => a - b);

Նվազման կարգով տեսակավորելու դեպքում՝

numArray.sort((a, b) => b - a);

Եվ ամենավերջում ներկայացնեմ մի քանի հետաքրքիր եղանակ, թե ինչպես տեսակավորել թվերի զանգվածը՝ ստանալով էլեմենտների լրիվ պատահական հերթականություն։ Դրա համար կարող ենք որպես արգումենտsort մեթոդին հաղորդել հետևյալ ֆունկցիաները՝

const shuffle = (a, b) => 0.5 - Math.random();
myArray.sort(shuffle);
const shuffle2 = (a, b) => Math.random() - Math.random();
myArray.sort(shuffle2);
const shuffle3 = (a, b) => a * Math.random() - b * Math.random();
myArray.sort(shuffle3);

Ամեն կանչի արդյունքում կստանանք տարբեր արդյունքներ, և այս եղանակը երբեմն կիրառվում է որոշ խնդիրների լուծման համար։