Σε αυτόν τον οδηγό θα δούμε πως μπορούμε να τα ταξινομήσουμε και να τα ομαδοποιήσουμε σύνολα με την χρήση διαφόρων τεχνικών μέσα από την Linq.js. Για να μπορέσουμε να σας προσφέρουμε κάποια παραδείγματα χρήσης των εντολών κάναμε χρήση του συνόλου «people.json» το οποίο μπορείτε να το αποκτήσετε από προηγούμενη δημοσίευση κάνοντας κλικ εδώ.
OrderBy & OrderByDescending
Αν θέλουμε ένα σύνολο να το ταξινομήσουμε με αύξουσα σειρά, επιλέγοντας το κατάλληλο χαρακτηριστικό μέσα από τα αντικείμενα του συνόλου, τότε η εντολή OrderBy αναλαμβάνει κάτι τέτοιο. Παρέχει και τους δύο τύπους χρήσης των επιλογής κριτηρίων (string, function) και μπορούν να χρησιμοποιηθούν μέχρι και δυο παράμετροι όπου η πρώτη είναι το value κάθε περίπτωσης ενώ η δεύτερη το index της.
Αρχείο: order-by-1.js
Enumerable.From(people).OrderBy("$.age").ToArray();
Enumerable.From(people).OrderBy(function(value, index) {
return value.age;
}).ToArray();
Αποτέλεσμα:
Παρομοίως με την OrderBy η OrderByDescending μας παρέχει την δυνατότητα να ταξινομήσουμε ένα σύνολο δεδομένων με συγκεκριμένα κριτήρια σε φθίνουσα σειρά. Παρέχει και τους δυο τύπους χρήσης επιλογής κριτηρίων (string, function) και μπορούν να χρησιμοποιηθούν μέχρι και δυο παράμετροι οπού η πρώτη είναι το value κάθε περίπτωσης ενώ η δεύτερη το index της.
Αρχείο: order-by-descending-1.js
Enumerable.From(people).OrderByDescending("$.age").ToArray();
Enumerable.From(people).OrderByDescending(function(value, index) {
return value.age;
}).ToArray();
Αποτέλεσμα:
Αν χρησιμοποιήσουμε δεύτερη OrderBy ή OrderByDescending μετά την πρώτη η δεύτερη θα ακυρώσει το αποτέλεσμα της πρώτης, και θα ξεκινήσει την ταξινόμηση από την αρχή.
Αρχείο: second-order.js
Enumerable.From(people).OrderBy("$.age").OrderByDescending("$.age").ToArray();
Αποτέλεσμα:
Επίσης καθότι Έλληνες χρησιμοποιούμε ελληνικούς χαρακτήρες στα προγράμματά μας κατά την πλειοψηφία των περιπτώσεων οι παραπάνω εντολές λαμβάνουν υπόψη και τους ελληνικούς χαρακτήρες σε σωστή κατά σειρά ταξινόμηση.
Αρχείο: order-by-descending-2.js
var test = [
{ a: "Κωνσταντίνος" },
{ a: "Konstantinos" },
{ a: "Δημήτριος" },
{ a: "Dimitrios" }
];
Enumerable.From(test).OrderByDescending("$.a").ToArray();
Αποτέλεσμα:
ThenBy & ThenByDescending
Η εντολή ThenBy είναι μια συνδυαστική εντολή ταξινόμησης η οποία λαμβάνει συνήθως μέρος μετά από την εντολή OrderBy ή την OrderByDescending. Η ThenBy αναλαμβάνει να ταξινομήσει κατά αύξουσα σειρά μετά από την πρώτη ταξινόμηση με βάση το εκάστοτε κριτήριο που θα της ορίσουμε το σύνολο μας. Έτσι αν είχαμε ταξινομήσει το σύνολο μας OrderBy(“$.gender”) τότε αν θέλουμε κάθε gender να ταξινομηθεί κατά αύξουσα με βάση την ηλικία τότε θα πούμε αμέσως μετά το OrderBy, ThenBy(“$.age”). Παρέχονται επίσης δυο τρόποι δήλωσης κριτηρίων (string, function) και μπορούν να χρησιμοποιηθούν όπως και σε όλες τις προηγούμενες order μέχρι και δυο παράμετροι οπού η πρώτη είναι το value και η δεύτερη το index κάθε περίπτωσης.
Αρχείο: then-by.js
Enumerable.From(people).OrderBy("$.gender").ThenBy("$.age").ToArray();
Enumerable.From(people).OrderBy("$.gender").ThenBy(function(value,index){
return value.age;
}).ToArray();
Αποτέλεσμα:
H εντολή ThenByDescending είναι μια συνδυαστική εντολή ταξινόμησης όπως την ThenBy με μόνη διαφορά ότι γίνεται σε φθίνουσα σειρά.
Αρχείο: then-by-descending.js
Enumerable.From(people).OrderBy("$.gender").ThenByDescending("$.age").ToArray();
Enumerable.From(people).OrderBy("$.gender").ThenByDescending(function(value,index){
return value.age;
}).ToArray();
Αποτέλεσμα:
Μπορούμε να ορίσουμε όσες ThenBy και ThenByDescending θέλουμε την μια μετά την άλλη και όλες θα λαμβάνουν υπόψη την προηγούμενη ταξινόμηση πριν προχωρήσουν στην δική τους.
Αρχείο: then-by-1.js
Enumerable.From(people).OrderBy("$.gender").ThenBy("$.age").ThenBy("$.first_name").ToArray();
Enumerable.From(people).OrderBy("$.gender").ThenByDescending("$.age").ThenByDescending("$.first_name").ToArray();
Αποτέλεσμα:
Καθώς επίσης και συνδυασμό τους.
Αρχείο: then-by-2.js
Enumerable.From(people).OrderBy("$.gender").ThenBy("$.age").ThenByDescending("$.first_name").ToArray();
Αποτέλεσμα:
Reverse
Η Reverse είναι μια εντολή με την οποία μπορούν να αντιστρέψουμε ένα πίνακα που αναφέρεται σε έναν σύνολο, από την κανονική του σειρά στην αντίθετη, αυτό σημαίνει το πρώτο στοιχείο του πίνακα να γίνει τελευταίο και το τελευταίο πρώτο και όλα τα ενδιάμεσα αντίθετα στην φορά τους. Αν για παράδειγμα είχαμε το σύνολο [1,2,3,4,5] η Reverse θα μας έδινε ως αποτέλεσμα [5,4,3,2,1].
Αρχείο: reverse.js
var numbers = [1,2,3,4,5];
Enumerable.From(numbers).Reverse().ToArray();
Αποτέλεσμα:
Shuffle
Με αυτή την εντολή μπορούμε να πάρουμε σε τυχαία σειρά όλα τα στοιχεία ενός συνόλου. Αυτό που κάνει η Shuffle είναι να «ανακατεύει» το σύνολο μας δίνοντας μας έτσι τυχαίες θέσεις στα στοιχεία του αρχικού πίνακα-συνόλου που εισήγαμε σε αυτήν.
Αρχείο: shuffle.js
var numbers = [1,2,3,4,5];
Enumerable.From(numbers).Shuffle().ToArray();
Αποτέλεσμα:
GroupBy
Η GroupBy (όπως και η PartitionBy που θα δούμε στην συνέχεια) είναι μια από τις πιο περίπλοκες εντολές της Linq.js. Αυτό που μας προσφέρει επί της ουσίας είναι ομαδοποίηση των εγγραφών μας με βάση ένα από τα χαρακτηριστικά του συνόλου. Έτσι αν έχουμε για παράδειγμα ομαδοποίηση κατά το φύλο των ατόμων στην λίστα people, θα δημιουργηθούν δύο groups ένα με όλους τους άνδρες και ένα με όλες τις γυναίκες.
Αν θέλουμε να κάνουμε μια απλή τυπική ομαδοποίηση τότε το μόνο που χρειάζεται για να λειτουργήσει κατ' αυτόν τον τρόπο η GroupBy είναι μια παράμετρος επιλογής χαρακτηριστικού με βάση του οποίου θα γίνει η ομαδοποίηση. Η GroupBy τότε θα μας επιστρέψει έναν πίνακα με όσες διακριτές τιμές διαθέτει το σύνολο μας με βάση το χαρακτηριστικό που διαλέξαμε. Αν για παράδειγμα διαλέγαμε το φύλλο τότε το πλήθος των στοιχείων του πίνακα θα είναι δυο, ένα που θα αντιστοιχεί στο «Male» και ένα που θα αντιστοιχεί στο «Female». Η δομή ωστόσο του αποτελέσματος έχει ως εξής, σε κάθε ένα από αυτά τα αντικείμενα θα υπάρχει ένα χαρακτηριστικό «key()» το οποίο μας επιστρέφει το «κλειδί» για την συγκεκριμένη ομαδοποίηση (σε κάθε περίπτωση η «Male» ή «Female») και ένα χαρακτηριστικό «source» που θα περιέχει όλες εκείνες τις εγγραφές του συνόλου μας που περιέχουν το αντίστοιχο κλειδί και έχουν ομαδοποιηθεί με βάση αυτό. Το παρακάτω παράδειγμα δείχνει την πράξη της παραπάνω δομής:
Αρχείο: group-by-1.js
Enumerable.From(people).GroupBy("$.gender").ToArray();
Enumerable.From(people).GroupBy(function(value){
return value.gender;
}).ToArray();
Αποτέλεσμα:
Ωστόσο αν θέλουμε να μετασχηματίσουμε τα δεδομένα που θα επιστραφούν στην λίστα του «source» αποκλείοντας έτσι κάποια χαρακτηριστικά ή διαλέγοντας μόνο κάτι συγκεκριμένο μέσα από αυτά τότε μπορούμε να το κάνουμε αυτό με την χρήση δεύτερης παραμέτρου, οπού σε αυτήν μπορούμε να μετασχηματίσουμε τα δεδομένα μας στο πως θέλουμε να επιστραφούν. Στο παρακάτω παράδειγμα επιλέξαμε να επιστρέψουμε το ονοματεπώνυμο της κάθε περίπτωσης.
Αρχείο: group-by-2.js
Enumerable.From(people).GroupBy("$.gender","$ => $.first_name + ' ' + $.last_name").ToArray();
Enumerable.From(people).GroupBY("$.gender",function(value){
return value.first_name + ' ' + value.last_name;
}).ToArray();
Αποτέλεσμα:
Τώρα αν η δομή των αποτελεσμάτων δεν μας αρέσει η δεν μας βολεύει όπως η GroupBy επιστρέφει τα αποτελέσματα μπορούμε κι αυτό να το αλλάξουμε χρησιμοποιώντας μια τρίτη παράμετρο όπου μέσα σε αυτήν δίνεται το ΑΠΟΤΕΛΕΣΜΑ της ομαδοποίησης και όχι το αρχικό σύνολο, επομένως τα standar χαρακτηριστικά της κάθε value θα είναι ένα key() και το source, επομένως επιλέγουμε προσεκτικά και μετασχηματίζουμε ακριβώς όπως θέλουμε τα αποτελέσματα μας. Στο παρακάτω παράδειγμα μετασχηματίζουμε το key() σε κανονικό property value έτσι ώστε να μπορούμε να το δούμε και στην κονσόλα, και τοποθετούμε το source σε ένα property «grouped».
Αρχείο: group-by-3.js
Enumerable.From(people).GroupBy("$.gender","$ => $.first_name + ' ' + $.last_name","key, grouped => {key: key, data: grouped.source}").ToArray();
Enumerable.From(people).GroupBy(function(value){
return value.gender;
},function(value){
return value.first_name + " " + value.last_name;
},function(key,grouped){
return {key: key, data: grouped.source};
}).ToArray();
Αποτέλεσμα:
Τέλος η GroupBy μας δίνει έναν ακόμη Selector ως τελευταία παράμετρο για το GroupBy όπου μπορούμε να διαχωρίσουμε τα αποτελέσματα σε δυο μέρη αναλόγως το αν ικανοποιείται η συνθήκη το Selector ή όχι. Έτσι θα επιστραφεί ένα σύνολο με βάση την δομή που προεπιλέξαμε αλλα με δυο εγγραφές ή πρώτη θα διαθέτει όλα εκείνα τα στοιχεία που ικανοποιούν τον selector (επιστρέφει true ) και μια ακόμη εγγραφή που δεν ικανοποιούν τον selector (επιστρέφει false). Στο παρακάτω παράδειγμα επιλέγουμε να διαλέξουμε όλες εκείνες τις εγγραφές όπου η Ηλικία των εγγραφών είναι πάνω από 35 χρονών. Αυτό θα διαχωρίσει το σύνολο μας σε δυο υποσύνολα όσοι είναι πάνω από 35 χρονών και όσοι είναι από 35 και κάτω. Προσοχή στο παρακάτω παράδειγμα έχουμε αλλάξει τους αρχικούς selectors από gender σε age προκειμένου να μπορέσουμε να πραγματοποιήσουμε ομαδοποίηση με βάση αριθμητικό στοιχείο.
Αρχείο: group-by-4.js
Enumerable.From(people).GroupBy("$.age","$ => $.age +' '+ $.first_name + ' ' + $.last_name","key,grouped => {key: key, data: grouped.source}","$ => $ > 35").ToArray();
Enumerable.From(people).GroupBy(function(value){
return value.age;
},function(value){
return value.age+" "+value.first_name + " " + value.last_name;
},function(key,grouped){
return {key: key, data: grouped.source};
},function(key){
return key > 35;
}).ToArray();
Αποτέλεσμα:
PartitionBy
Η ParitionBy λειτουργεί με παρόμοιο τρόπο με την GroupBy, παίρνει δηλαδή τα ίδια ορίσματα κάνει τις ίδιες επιλογές στα αποτελέσματα της με μόνη διαφορά ότι στην περίπτωση της PartitionBy επιλέγονται τα στοιχεία εκτός από την τιμή τους και με βάση την θέση στην οποία βρίσκονται. Αυτό σημαίνει πως αν για παράδειγμα έχουμε 1 Male κατά σειρά ύστερα 1 Female και ύστερα 4 Males, η ParitionBy θα ομαδοποιήσει το 1 Male μόνο του, ύστερα το Female ξανά μόνο του και τα 4 Males που ακολουθούν στην σειρά, μαζί. Ας δούμε πως γίνεται αυτό με το παρακάτω παράδειγμα:
Αρχείο: partition-by-1.js
Enumerable.From(people).PartitionBy("$.gender").ToArray();
Enumerable.From(people).PartitionBy(function(value){
return value.gender;
}).ToArray();
Αποτέλεσμα:
Μπορούμε να επιλέξουμε συγκεκριμένη δομή με την οποία κάθε εγγραφή θα επιστραφεί στα αποτελέσματα όπως ακριβώς και στην GroupBy που είδαμε προηγουμένως, με τον κατάλληλο Selector μπορούμε για παράδειγμα να διαλέξουμε να επιστραφεί μόνο η ηλικία το όνομα και το επώνυμο κάθε εγγραφής ως ένα απλό string, και τίποτε άλλο.
Αρχείο: partition-by-2.js
Enumerable.From(people).ParitionBy("$.gender","$ => $.first_name + ' ' + $.last_name").ToArray();
Enumerable.From(people).ParitionBy("$.gender",function(value){
return value.first_name + ' ' + value.last_name;
}).ToArray();
Αποτέλεσμα:
Παρομοίως με την GroupBy τα αποτελέσματα ακολουθούν την δομή «Key()» και «source» πράγμα το οποίο μπορούμε να αλλάξουμε με selector ως τρίτη παράμετρο στην PartitionBy.
Αρχείο: partition-by-3.js
Enumerable.From(people).ParitionBy("$.gender","$ => $.first_name + ' ' + $.last_name","key, grouped => {key: key, data: grouped.source}").ToArray();
Enumerable.From(people).ParitionBy(function(value){
return value.gender;
},function(value){
return value.first_name + " " + value.last_name;
},function(key,grouped){
return {key: key, data: grouped.source};
}).ToArray();
Αποτέλεσμα:
Όπως και με την GroupBy μπορούμε να διαχωρίσουμε τα επιμέρους κομμάτια σε επιμέρους κομμάτια του συνόλου πάλι ικανοποιώντας μια συγκεκριμένη συνθήκη όπως κάναμε και προηγουμένους με την ομαδοποίηση. Προσοχή! Για να φανεί η διαφορά στον τρόπο με τον οποίο λειτουργεί συγκεκριμένη λειτουργία έχουμε αλλάξει τον πρώτο Selector σε age.
Αρχείο: partition-by-4.js
Enumerable.From(people).PartitionBy("$.age","$ => $.age +' '+ $.first_name + ' ' + $.last_name","key,grouped => {key: key, data: grouped.source}","$ => $ > 35").ToArray();
Enumerable.From(people).PartitionBy(function(value){
return value.age;
},function(value){
return value.age+" "+value.first_name + " " + value.last_name;
},function(key,grouped){
return {key: key, data: grouped.source};
},function(key){
return key > 35;
}).ToArray();
Αποτέλεσμα:
BufferWithCount
Η εντολή BufferWithCount τεμαχίζει ένα σύνολο δεδομένων σε επιμέρους σύνολα με βάση έναν αριθμό που συμβολίζει το πλήθος των στοιχείων που θέλουμε τα επιμέρους υποσύνολα να έχουν. Είναι μια πολύ απλή εντολή η οποία ως παράμετρο δέχεται έναν ακέραιο αριθμό.
Αρχείο: buffer-with-count.js
Enumerable.From(people).BufferWithCount(4).ToArray();
Αποτέλεσμα: