Για να λειτουργήσει η LINQ.js σε κάποια σελίδα μας θα πρέπει πρώτα να έχουμε προσθέσει το αντίστοιχο script tag με src εκείνο του αρχείου linq.js είτε από τον server μας είτε από μέσω κάποιου cdn service. Αν θέλετε να χρησιμοποιήσετε cdn μπορείτε να βρείτε αντίστοιχα links από την υπηρεσία cdnjs, σε αυτό το link.
Ο τρόπος που προστίθεται ένα javascript αρχείο στην σελίδα μας περιγράφεται αναλυτικά εδώ.
Αφού προσθέσουμε το script στην σελίδα μας, μπορούμε να χρησιμοποιήσουμε την LINQ.js μέσω της μεταβλητής «Enumerable» ή οποία πλέον περιλαμβάνει όλες τις λειτουργίες της LINQ.
Προκειμένου να μπορέσουμε να χρησιμοποιήσουμε όλες τις δυνατότητες που μας προσφέρονται από το framework θα πρέπει πρώτα να έχουμε ένα dataset (σύνολο δεδομένων) στο οποίο θα εφαρμόσουμε την κάθε αντίστοιχη λειτουργία. Γι' αυτόν τον λόγο σε όλα τα παραδείγματα μας θα χρησιμοποιηθεί το παρακάτω dataset με όνομα «got», το οποίο αποτελεί όλα τα επεισόδια της έβδομης season του Game Of Thrones την εποχή που αυτός ο οδηγός γράφονταν.
var got = [
{
"id":937256,
"name":"Dragonstone",
"season":7,
"number":1,
"airdate":"2017-07-16",
"runtime":59,
"image":{
"medium":"http://static.tvmaze.com/uploads/images/medium_landscape/120/302038.jpg",
"original":"http://static.tvmaze.com/uploads/images/original_untouched/120/302038.jpg"
},
"summary":"Jon organizes the defense of the North. Cersei tries to even the odds. Daenerys comes home.",
},
{
"id":1221410,
"name":"Stormborn",
"season":7,
"number":2,
"airdate":"2017-07-23",
"runtime":59,
"image":{
"medium":"http://static.tvmaze.com/uploads/images/medium_landscape/120/302047.jpg",
"original":"http://static.tvmaze.com/uploads/images/original_untouched/120/302047.jpg"
},
"summary":"Daenerys receives an unexpected visitor. Jon faces a revolt. Tyrion plans the conquest of Westeros.",
},
{
"id":1221411,
"name":"The Queen's Justice",
"season":7,
"number":3,
"airdate":"2017-07-30",
"runtime":63,
"image":{
"medium":"http://static.tvmaze.com/uploads/images/medium_landscape/122/306938.jpg",
"original":"http://static.tvmaze.com/uploads/images/original_untouched/122/306938.jpg"
},
"summary":"Daenerys holds court. Cersei returns a gift. Jaime learns from his mistakes.",
},
{
"id":1221412,
"name":"The Spoils of War",
"season":7,
"number":4,
"airdate":"2017-08-06",
"runtime":50,
"image":{
"medium":"http://static.tvmaze.com/uploads/images/medium_landscape/123/307677.jpg",
"original":"http://static.tvmaze.com/uploads/images/original_untouched/123/307677.jpg"
},
"summary":"Arya gets to the final destination. Daenerys takes it upon herself to strike back.",
},
{
"id":1221413,
"name":"Eastwatch",
"season":7,
"number":5,
"airdate":"2017-08-13",
"runtime":59,
"image":{
"medium":"http://static.tvmaze.com/uploads/images/medium_landscape/124/310839.jpg",
"original":"http://static.tvmaze.com/uploads/images/original_untouched/124/310839.jpg"
},
"summary":"Daenerys demands loyalty from the surviving Lannister soldiers; Jon heeds Bran's warning about White Walkers on the move; Cersei vows to vanquish anyone or anything that stands in her way.",
},
{
"id":1221414,
"name":"Beyond the Wall",
"season":7,
"number":6,
"airdate":"2017-08-20",
"runtime":70,
"image":{
"medium":"http://static.tvmaze.com/uploads/images/medium_landscape/125/312651.jpg",
"original":"http://static.tvmaze.com/uploads/images/original_untouched/125/312651.jpg"
},
"summary":"Jon's mission continues north of the wall, but the odds against his ragged band of misfits may be greater than he imagined.",
},
{
"id":1221415,
"name":"The Dragon and the Wolf",
"season":7,
"number":7,
"airdate":"2017-08-27",
"runtime":81,
"image":{
"medium":"http://static.tvmaze.com/uploads/images/medium_landscape/125/314502.jpg",
"original":"http://static.tvmaze.com/uploads/images/original_untouched/125/314502.jpg"
},
"summary":"Cersei sits on the Iron Throne; Daenerys sails across the Narrow Sea; Jon Snow is King in the North, and winter is finally here.",
}
];
Οι εντολές τις LINQ λειτουργούν συνήθως με μια συγκεκριμένη σειρά:
- Πρώτα μια εντολή επιλογής αναλαμβάνει να ορίσει το σύνολο δεδομένων για τις επερχόμενες λειτουργίες,
- Ύστερα μια εντολή ή ένα σύνολο εντολών αναλαμβάνουν να εκτελέσουν τις αντίστοιχες τους λειτουργίες επιδρώντας πάνω στο σύνολο το οποίο εισάχθηκε αλλά χωρίς να το αλλάξουν,
- Τελευταίο και προαιρετικό, μια εντολή αναλαμβάνει να καθορίσει την μορφή με την οποία θα επιστραφούν τα αποτελέσματα τις προηγούμενης διαδικασίας. Αν δεν χρησιμοποιηθεί κάποιο είδος μεθόδου επιστροφής μορφής αποτελεσμάτων τότε επιστρέφεται ένα αντικείμενο τύπου «Enumerable» (αποτελεί τύπο δεδομένων της Linq.js) το οποίο μπορούμε να χρησιμοποιήσουμε στην πορεία όπως θέλουμε και να εξάγουμε από αυτό τα αποτελέσματα επίσης όπως θέλουμε.
Προσοχή! Σε όλες (ή τις περισσότερες) εντολές διαχείρισης συνόλου δεδομένων μέσω της LINQ θα χρησιμοποιήσουμε την εντολή ToArray() για να επιστρέψουμε τα δεδομένα σε μορφή πίνακα έτσι ώστε να είναι εύκολα αναγνωρίσιμα στο ανθρώπινο μάτι.
Σε αυτό το μέρος του οδηγού θα δούμε όλες εκείνες τις λειτουργίες μέσω των οποίων μπορούμε να δημιουργήσουμε νέα δεδομένα βασιζόμενοι σε αυτά που ήδη έχουμε.
Choice & Take
Με την εντολή Choice μπορούμε να «διαλέξουμε» τυχαία στοιχεία μέσα από ένα σύνολο δεδομένων. Η είσοδος της μπορεί να είναι ένας πίνακας από στοιχεία, ή μεμονωμένα στοιχεία χωρισμένα με κόμμα.
Η εντολή Take είναι μια εντολή μέσω της οποίας μπορούμε να «πάρουμε» μέσα από ένα παραγόμενο αποτέλεσμα ένα σύνολο από ότι παράχθηκε. Η Take δέχεται ως είσοδο έναν αριθμό που συμβολίζει το πόσα αποτελέσματα θέλουμε να επιστραφούν και στην περίπτωση της Choice η Take λειτουργεί έως πόσα τυχαία αντικείμενα θα θέλαμε να επιστραφούν ως αποτέλεσμα. Ένα παράδειγμα χρήσης της Choice σε συνδυασμό με την Take βρίσκεται παρακάτω:
Enumerable.Choice("G","A","M","E").Take(10).ToArray();
Enumerable.Choice(["G","A","M","E"]).Take(10).ToArray();
Παρατηρούμε πως είτε εισάγουμε έναν πίνακα ως είσοδο στην Choice είτε εισάγουμε διαφορετικά μεμονωμένα στοιχεία, το αποτέλεσμα είναι ίδιο, ένα σύνολο από τυχαίους χαρακτήρες μέσα από το δείγμα που του εισήγαμε.
Η Choice είναι χρήσιμη σε περιπτώσεις όπως για παράδειγμα όταν επρόκειτο για κάποια κλήρωση που αφορά παραπάνω από έναν επιτυχόντες.
Cycle & Take
Η Cycle κάνει αυτό που η ονομασία της προδίδει, στηριζόμενη σε ένα σύνολο δεδομένων που εισάγουμε σε αυτήν και συγκεκριμένα με την σειρά στην οποία βρίσκεται αυτό το σύνολο, κάνει «κύκλους» στο ίδιο σύνολο για όσο πλήθος θέλουμε να παράγουμε μέσα από την Take(). Αυτό σημαίνει πως αν εισάγουμε στην cycle το σύνολο «"Δευτέρα", "Τρίτη", "Τετάρτη"» και διαλέξουμε πως θέλουμε 6 από αυτά τότε η Cycle δεν θα διαλέξει τυχαία όπως έκανε η Choice αλλά θα ξεκινήσει από την «Δευτέρα», θα συνεχίσει στα «Τρίτη» και «Τετάρτη» και όταν πια δεν έχει άλλα στοιχεία για να διαλέξει από το σύνολο, θα ξεκινήσει πάλι από την αρχή, έτσι το αποτέλεσμα που θα παραχθεί θα είναι «Δευτέρα, Τρίτη, Τετάρτη, Δευτέρα, Τρίτη, Τετάρτη».Η Cycle δέχεται είτε μεμονωμένα στοιχεία είτε πίνακα.
Enumerable.Cycle(99,"Learncode",{test:true}).Take(10).ToArray();
Enumerable.Cycle([99,"Learncode",{test:true}]).Take(10).ToArray();
Empty
Η εντολή Empty επιστρέφει ένα αντικείμενο τύπου Enumerable το οποίο δεν περιλαμβάνει απολύτως τίποτα ως περιεχόμενο στο σύνολο του , γι' αυτό κι αν προσπαθήσουμε να επιστρέψουμε αποτελέσματα σε μορφή πίνακα θα λάβουμε ως αποτέλεσμα έναν κενό πίνακα.
Αρχείο: empty.js
Enumerable.Empty().ToArray();
Αποτέλεσμα:
From
Είναι μια εντολή που θα χρησιμοποιηθεί κατά κόρον στην χρήση της LINQ.js και αυτό διότι αποτελεί μια δηλωτική λειτουργία για το σύνολο δεδομένων στο οποίο θα επεξεργαστούμε. Αν ξέρετε SQL η LINQ μοιάζει λίγο σε αυτήν με τις ονομασίες των λειτουργιών της. Αν εισάγουμε ένα σύνολο και ύστερα απλά το επιστρέψουμε με την ToArray() αυτο θα μας επιστρέψει τον ίδιο τον πίνακα έτσι όπως των εισήγαμε.
Η εντολή From μπορεί να δεχθεί μια ποικιλία από αντικείμενα εισόδου, όπως έναν πίνακα, ένα αντικείμενο, html στοιχεία (elements), έναν αριθμό ή ακόμη κι ένα αλφαριθμητικό. Μερικά παραδείγματα χρήσης ακολουθούν στο παρακάτω παράδειγμα:
Αρχείο: From.js
Enumerable.From([7,"GAME","OF","THRONES", true, function test(){}]).ToArray(); //Πίνακας
Enumerable.From({title: "Game Of Thrones", season: 7, addEpisode:function(){}, hasMore: true }).ToArray(); //Object
Enumerable.From(document.getElementsByTagName('a')).ToArray();
Enumerable.From(5).ToArray(); //Number
Enumerable.From("GOT").ToArray(); //String
Αποτέλεσμα:
Return
Η εντολή Return δέχεται ως είσοδο έναν αριθμό, string ή array και επιστρέφεται ως ένα Enumerable Object. Ωστόσο αν προσθέσουμε στο τέλος ToArray() θα επιστραφεί ως πίνακας. Προφανώς η Return υπάρχει προκειμένου να μπορούμε να μετατρέψουμε απλά δεδομένα σε αντικείμενα Enumerable της LINQ.js. Η χρήση της είναι απλή:
Αρχείο: return.js
Enumerable.Return("LearnCode");
Enumerable.Return(5);
Enumerable.Return(["Konstantinos","LearnCode"]);
Αποτέλεσμα:
Matches
Εκτός από την επεξεργασία και προσπέλαση ενός πίνακα δεδομένων η LINQ.js μπορεί να ελέγξει κι αν μια κανονική έκφραση υπάρχει μέσα σε ένα αλφαριθμητικό.Αυτό επιτυγχάνεται με την χρήση της εντολής Matches, όπου μπορούν να υπάρξουν τρεις παραδοχές της.
- Εισάγοντας ως παραμέτρους ένα αλφαριθμητικό ελέγχου και μια κανονική έκφραση,
- Εισάγοντας ως παραμέτρους δυο αλφαριθμητικά, το πρώτο αποτελεί το αλφαριθμητικό στο οποίο θα δράσει το μοτίβο το οποίο εισάγουμε ως δεύτερο,
- Εισάγοντας ως παραμέτρους τρία αλφαριθμητικά εκ των οποίων το ένα (το τελευταίο) θα αποτελέσει τα flags options του αντίστοιχης υποτιθέμενης κανονικής έκφρασης.
Έτσι με όλα τα παραπάνω ας υποθέσουμε πως θέλουμε να εντοπίσουμε όπου εμφανίζεται η λέξη «got» μέσα στην φράση «got1 is the best series ever, GOT2 has 1 more #gOt season».
Αρχείο: Matches.js
var s = "got1 is the best series ever, GOT2 has 1 more #gOt season";
Enumerable.Matches(s, /got/i).ToArray();
Enumerable.Matches(s, "got").ToArray();
Enumerable.Matches(s, "got", "i").ToArray();
Αποτέλεσμα:
Το αποτέλεσμα που μας επιστρέφεται είναι ένας πίνακας όπου στην πρώτη του θέση [0] βρίσκεται το κείμενο εκείνο το οποίο πληροί το μοτίβο σε κάθε περίπτωση, στην επόμενη θέση με ετικέτα Index το ακριβές σημείο στο οποίο βρέθηκε αυτό το λεκτικό, και στην τρίτη θέση με ετικέτα input η είσοδος από την οποία προέκυψε το εν λόγω αποτέλεσμα. Αν στην αναζήτηση μας είχαμε συμπεριλάβει ρύθμιση για αναζήτηση συγκεκριμένου χαρακτήρα αυτός θα εμφανιστεί στην δεύτερη θέση του πίνακα χωρίς κάποια ετικέτα ονόματος.
Αν θέλαμε να διαλέξουμε το επόμενο χαρακτήρα μετά από την λέξη που ψάχνουμε θα προσθέταμε την επιλογή «(.)» μέσα στην κανονική έκφραση:
Αρχείο: Matches2.js
var s = "got1 is the best series ever, GOT2 has 1 more #gOt season";
Enumerable.Matches(s, /got(.)/i).ToArray();
Enumerable.Matches(s, "got(.)").ToArray();
Enumerable.Matches(s, "got(.)", "i").ToArray();
Αποτέλεσμα:
Range
Η εντολή Range μα επιστρέφει ένα σύνολο δεδομένων το οποίο δημιουργείται με βάση τα στοιχεία εισόδου που θα δώσουμε ως παραμέτρους. Υπάρχουν δυο τρόποι για να χρησιμοποιήσουμε την λειτουργία αυτή, είτε να δηλώσουμε δυο μόνο αριθμητικούς ακέραιους παραμέτρους, όπου η πρώτη αποτελεί το σημείο εκκίνησης και το δεύτερο το πλήθος των στοιχείων που θέλουμε να επιστραφούν , είτε να συμπεριλάβουμε και έναν τρίτο ο οποίος θα αποτελέσει το βήμα με το οποίο θα προχωράει η λίστα των παραγόμενων αριθμών.Η Range λειτουργεί προσθετικά αυτό σημαίνει πως προστίθεται κάτι σε κάθε επόμενο στοιχείο.
Αρχέιο: range.js
Enumerable.Range(-20,5).ToArray();
Enumerable.Range(-20,5,8).ToArray();
Αποτέλεσμα:
RangeDown
Λειτουργεί όπως η Range μόνο που σε αυτή την περίπτωση δεν λειτουργεί προσθετικά αλλά αφαιρετικά. Αυτό σημαίνει πως από το σημείο εκκίνησης έως το πλήθος των στοιχείων που θέλουμε να παραχθούν θα αφαιρούνται τιμές.
Αρχείο: rangeDown.js
Enumerable.RangeDown(-20,5).ToArray();
Enumerable.RangeDown(-20,5,8).ToArray();
Αποτέλεσμα:
RangeTo
Εκτός από τους δυο διαφορετικούς τρόπους (αφαιρετικό – προσθετικό) υπάρχει και μια πιο γενικευμένη χρήση του Range μέσα από την δήλωση του σημείου εκκίνησης και του σημείου λήξης σε τιμή αλλά όχι σε πλήθος των στοιχείων. Μέχρι στιγμής με το Range και το RangeDown δηλώναμε μια τιμή, έστω 3 ως σημείο εκκίνησης και ύστερα ένα πλήθος στοιχείων που θέλουν να επιστραφούν έστω 5. Αυτό αναλόγως την λειτουργία που διαλέγαμε (αν ήταν Range η RangeDown) πρόσθετε ή αφαιρούσε κατά ένα στοιχείο σε κάθε νέο αριθμό μέχρι το πλήθος τους να φτάσει αυτό που ζητούσαμε. Δηλαδή στην περίπτωση του 3 έως 5 η λειτουργία επέστρεφε 3,4,5,6,7 ή 3,2,1,0,-1 (με rangedown). Τώρα πλέον με την RangeTo δεν χρειάζεται να δηλώσουμε πλήθος αλλά τιμή στην οποία θέλουμε να καταλήξουμε, έτσι το παραπάνω για την Range αν το γράφαμε σε RangeTo θα έπρεπε να της δώσουμε σημείο εκκίνησης και σημείο τέλους δλδ 3 έως 7 και όχι 3 έως 5. Η RangeTo αντιλαμβάνεται αυτόματα αν πρόκειται για αφαίρεση ή πρόσθεση με βάση την διαφορά του πρώτου και του δεύτερου αριθμού. Επίσης είναι δυνατό να χρησιμοποιηθεί και βηματισμός στην εν λόγω λειτουργία.
Αρχείο: rangeTo.js
Enumerable.RangeTo(3,-5).ToArray();
Enumerable.RangeTo(20,25).ToArray();
Enumerable.RangeTo(3,-5,2).ToArray();
Enumerable.RangeTo(20,25,3).ToArray();
Αποτέλεσμα:
Repeat
Το Repeat επιστρέφει ένα σύνολο δεδομένων βασιζόμενο σε μια μόνο τιμή την οποία και επαναλαμβάνει για όσο διάστημα εμείς του πούμε. Υπάρχουν δυο τρόποι για να αντλήσουμε αποτελέσματα από αυτόν τον τρόπο παραγωγής δεδομένων, είτε χρησιμοποιώντας την εντολή Take μετά από την Repeat με το αντίστοιχο πλήθος μέσα σε αυτό, είτε συμπεριλαμβάνοντας μέσα στις παραμέτρους του Repeat και ένα πλήθος το οποίο έρχεται δεύτερο στις δηλώσεις.
Προσοχή! Ποτέ μην χρησιμοποιήσετε την Repeat χωρίς να κάνετε χρήση του Take ή δίνοντας ένα πλήθος ως παράμετρο στο Repeat, διότι αυτό θα οδηγήσει σε ατέρμονη επανάληψη η οποία θα προκαλέσει και το κατάρρευση του Περιηγητή. Μπορείτε να δημιουργήσετε ένα σκέτο Enumerable Object χωρίς να δηλώσετε πλήθος άλλα ποτέ μην το καλέσετε αποτελέσματα από αυτό χωρίς να δηλώσετε το Take πριν από οποιαδήποτε τρόπο επιστροφής αποτελεσμάτων.
Αρχείο: repeat.js
Enumerable.Repeat("LearnCode").Take(5).ToArray();
Enumerable.Repeat("LearnCode",5).ToArray();
Αποτέλεσμα:
Generate
Το Generate αποτελεί μια λειτουργία παραγωγής δεδομένων με πιο πολύπλοκο τρόπο καθώς μπορεί να γίνει με την χρήση οποιαδήποτε μεθόδου ή λειτουργίας της Javascript ή που έχουμε γράψει εμείς. Δηλώνουμε μια μέθοδο, αν πρόκειται για public μέθοδο την οποία μπορεί να προσπελάσει η Enumerable από τον εσωτερικό της κώδικα τότε μπορούμε να την γράψουμε ως String, αν πρόκειται για δικιά μας function τότε μπορούμε είτε να συμπεριλάβουμε την μεταβλητή της ως παράμετρο, είτε να συγγράψουμε εκείνη την στιγμή μια function. Ότι θα επιστρέφει η Function αυτή είναι και η κάθε τιμή που θα υπάρχει στον παραγόμενο αποτέλεσμα. Παρομοίως πρέπει να δηλώσουμε πλήθος κι εδώ με έναν από τους δυο τρόπους είτε χρησιμοποιώντας πλήθος είτε χρησιμοποιώντας την Take.
Αρχείο: generate.js
Enumerable.Generate("Math.random()").Take(4).ToArray();
Enumerable.Generate(function(){
return Math.round(Math.random() * 100);
}).Take(4).ToArray();
Αποτέλεσμα:
ToInfinity
Η λειτουργία αυτή μπορεί να μας επιστρέψει αριθμούς από ένα σημείο εκκίνησης έως το συν άπειρο. Αυτό όμως αποτελεί κίνδυνο σε περίπτωση που δεν δηλωθεί ένα πλήθος, καθώς δεν μπορούμε να έχουμε άπειρους αριθμούς στην μνήμη RAM του υπολογιστή μας. Έτσι επί της ουσίας όταν καλείται η συγκεκριμένη μέθοδος δημιουργείται ένα Enumerable object το οποίο ύστερα μπορούμε να το καλέσουμε όποτε εμείς θέλουμε αλλάζοντας κάθε φορά το πλήθος το οποίο μπορεί να θέλουμε αλλά με το ίδιο σημείο εκκίνησης.Αν δεν εισάγουμε σημείο εκκίνησης τότε η μέτρηση ξεκινά από το 0.
Αρχείο: toInf.js
Enumerable.ToInfinity(-2).Take(5).ToArray();
Enumerable.ToInfinity().Take(5).ToArray();
Αποτέλεσμα:
ToNegativeInfinity
Η λειτουργία αυτή λειτουργεί όπως το ToInfinity αλλά με κατεύθυνση το αρνητικό άπειρο. Αν δεν εισάγουμε τιμή εκκίνησης όλα ξεκινούν από το 0.
Αρχείο: toNegativeInf.js
Enumerable.ToNegativeInfinity(2).Take(5).ToArray();
Enumerable.ToNegativeInfinity().Take(5).ToArray();
Αποτέλεσμα:
Unfold
Το Unfold λειτουργεί περίπου με παρόμοιο τρόπο όπως το Range και RangeDown μόνο που στην περίπτωση του Unfold δηλώνεται ένα σημείο εκκίνησης και η διαφορά με την οποία θα δημιουργηθούν τα στοιχεία που θα παραχθούν. Η δεύτερη παράμετρος μπορεί να είναι είτε ένα String της μορφής «$+5» όπου το $ αποτελεί το κάθε στοιχείο μεμονωμένα και το 5 αποτελεί την διαφορά που θέλουμε να έχει από το προηγούμενο του. Εναλλακτικά μπορεί να χρησιμοποιηθεί Function στην θέση του string όπου ως είσοδο δίνεται η τιμή του προηγούμενου στοιχείου, και έτσι μπορούμε να κάνουμε πιο περίπλοκους υπολογισμούς πριν επιστρέψουμε την τιμή που θέλουμε να δοθεί ως επόμενη.
Αρχείο: unfold.js
Enumerable.Unfold(5, "$+2").Take(10).ToArray();
Enumerable.Unfold(5, "$-2").Take(10).ToArray();
Αποτέλεσμα: