Σε αυτόν τον οδηγό θα δούμε πως μπορούμε να τα ταξινομήσουμε και να τα ομαδοποιήσουμε σύνολα με την χρήση διαφόρων τεχνικών μέσα από την Linq.js. Για να μπορέσουμε να σας προσφέρουμε κάποια παραδείγματα χρήσης των εντολών κάναμε χρήση του συνόλου «people.json» το οποίο μπορείτε να το αποκτήσετε από προηγούμενη δημοσίευση κάνοντας κλικ εδώ.

linqjs

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();

Αποτέλεσμα:

image

Παρομοίως με την 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();

Αποτέλεσμα:

image

Αν χρησιμοποιήσουμε δεύτερη OrderBy ή OrderByDescending μετά την πρώτη η δεύτερη θα ακυρώσει το αποτέλεσμα της πρώτης, και θα ξεκινήσει την ταξινόμηση από την αρχή.

Αρχείο: second-order.js

Enumerable.From(people).OrderBy("$.age").OrderByDescending("$.age").ToArray();

Αποτέλεσμα:

image

Επίσης καθότι Έλληνες χρησιμοποιούμε ελληνικούς χαρακτήρες στα προγράμματά μας κατά την πλειοψηφία των περιπτώσεων οι παραπάνω εντολές λαμβάνουν υπόψη και τους ελληνικούς χαρακτήρες σε σωστή κατά σειρά ταξινόμηση.

Αρχείο: order-by-descending-2.js

var test = [
    {   a: "Κωνσταντίνος"   }, 
    {   a: "Konstantinos"   }, 
    {   a: "Δημήτριος"      }, 
    {   a: "Dimitrios"      }
];
Enumerable.From(test).OrderByDescending("$.a").ToArray();

Αποτέλεσμα:

image

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();

Αποτέλεσμα:

image

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();

Αποτέλεσμα:

image

Μπορούμε να ορίσουμε όσες 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();

Αποτέλεσμα:

imageimage

Καθώς επίσης και συνδυασμό τους.

Αρχείο: then-by-2.js

Enumerable.From(people).OrderBy("$.gender").ThenBy("$.age").ThenByDescending("$.first_name").ToArray();

Αποτέλεσμα:

image

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();

Αποτέλεσμα:

image

Shuffle

Με αυτή την εντολή μπορούμε να πάρουμε σε τυχαία σειρά όλα τα στοιχεία ενός συνόλου. Αυτό που κάνει η Shuffle είναι να «ανακατεύει» το σύνολο μας δίνοντας μας έτσι τυχαίες θέσεις στα στοιχεία του αρχικού πίνακα-συνόλου που εισήγαμε σε αυτήν.

Αρχείο: shuffle.js

var numbers = [1,2,3,4,5];
Enumerable.From(numbers).Shuffle().ToArray();

Αποτέλεσμα:

image

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();

Αποτέλεσμα:

image

Ωστόσο αν θέλουμε να μετασχηματίσουμε τα δεδομένα που θα επιστραφούν στην λίστα του «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();

Αποτέλεσμα:

image

Τώρα αν η δομή των αποτελεσμάτων δεν μας αρέσει η δεν μας βολεύει όπως η 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();

Αποτέλεσμα:

image

Τέλος η 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();

Αποτέλεσμα:

image

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();

Αποτέλεσμα:

image

Μπορούμε να επιλέξουμε συγκεκριμένη δομή με την οποία κάθε εγγραφή θα επιστραφεί στα αποτελέσματα όπως ακριβώς και στην 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();

Αποτέλεσμα:

image

Παρομοίως με την 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();

Αποτέλεσμα:

image

Όπως και με την 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();

Αποτέλεσμα:

image

BufferWithCount

Η εντολή BufferWithCount τεμαχίζει ένα σύνολο δεδομένων σε επιμέρους σύνολα με βάση έναν αριθμό που συμβολίζει το πλήθος των στοιχείων που θέλουμε τα επιμέρους υποσύνολα να έχουν. Είναι μια πολύ απλή εντολή η οποία ως παράμετρο δέχεται έναν ακέραιο αριθμό.

Αρχείο: buffer-with-count.js

Enumerable.From(people).BufferWithCount(4).ToArray();

Αποτέλεσμα:

image