This article is currently in the process of being translated into Italian (~98% done).
Limiting data: the Take() & Skip() methods
Finora, in questo capitolo del tutorial dedicato a LINQ, abbiamo scoperto diversi modi per lavorare con le fonti di dati utilizzando LINQ. Ora è arrivato il momento di vedere come limitare la quantità di dati con cui lavorare. Questo è particolarmente utile quando si usa un database come fonte di dati, perché spesso si tratta di enormi quantità di righe, che consumano risorse per essere recuperate.
I metodi di cui parleremo in questo articolo si chiamano Take() e Skip() e, in combinazione, sono ottimi per eseguire operazioni come l'impaginazione di un sito web. In effetti, vengono spesso usati insieme, ma possono naturalmente essere usati anche da soli. Il metodo Take() consente di ottenere un numero X di elementi dall'origine dati, mentre Skip() consente di ignorare i primi X elementi. Un semplice esempio potrebbe essere il seguente:
List<string> names = new List<string>()
{
"John Doe",
"Jane Doe",
"Joe Doe",
"Jenna Doe",
};
var middleNames = names.Skip(1).Take(2).ToList();
foreach (var name in middleNames)
Console.WriteLine(name);
Creiamo una semplice lista di nomi e poi, per l'output, saltiamo il primo nome (Skip(1)) quindi prendiamo i successivi due nomi (Take(2)), lasciandoci in pratica solo i due nomi centrali dell'elenco.
Impaginazione di base con Skip() e Take()
Come si può vedere, entrambi i metodi Take() e Skip() sono molto semplici da usare, ma sono più interessanti da dimostrare con più dati di quelli che abbiamo usato in precedenza, quindi mi sono preso la libertà di creare un esempio leggermente più complesso, che dimostrerà meglio come questi metodi possono aiutarvi. Per prima cosa, ecco il codice:
using System;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
namespace LinqTakeSkip1
{
class Program
{
static void Main(string[] args)
{
CultureInfo usCulture = new CultureInfo("en-US");
XDocument xDoc = XDocument.Load("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
var cubeNodes = xDoc.Descendants().Where(n => n.Name.LocalName == "Cube" && n.Attribute("currency") != null).ToList();
var currencyRateItems = cubeNodes.Select(node => new
{
Currency = node.Attribute("currency").Value,
Rate = double.Parse(node.Attribute("rate").Value, usCulture)
});
int pageSize = 5, pageCounter = 0;
var pageItems = currencyRateItems.Take(pageSize);
while(pageItems.Count() > 0)
{
foreach (var item in pageItems)
Console.WriteLine(item.Currency + ": " + item.Rate.ToString("N2", usCulture));
Console.WriteLine("Press any key to get the next items...");
Console.ReadKey();
pageCounter++;
// Here's where we use the Skip() and Take() methods!
pageItems = currencyRateItems.Skip(pageSize * pageCounter).Take(pageSize);
}
Console.WriteLine("Done!");
}
}
}
Si tratta di un bel po' di codice, ma vediamo di analizzarlo. Nella prima parte, analizziamo una fonte XML disponibile pubblicamente di tassi di cambio. Questo mi dà l'opportunità di mostrare brevemente LINQ to XML, che è una parte molto interessante dell'ecosistema LINQ. Parleremo di LINQ to XML in un altro articolo, ma per ora vi basti sapere che lo usiamo per estrarre i nodi importanti dalla fonte XML e inserirli in oggetti anonimi, costituiti dal nome e dal tasso di cambio attuale della valuta, che useremo in seguito.
Ora abbiamo una bella fonte di dati di informazioni sulla valuta nella variabile currencyRateItems. Nell'ultima parte dell'esempio, usiamo questa fonte per fare una semplice impaginazione: estraiamo semplicemente 5 voci e poi chiediamo all'utente di premere un tasto per ottenere le successive 5 (o quante ne rimangono nella fonte). Per farlo, estraiamo le prime 5 voci e poi usiamo un ciclo while per estrarre continuamente le 5 voci successive, finché la fonte non è vuota. L'estrazione delle 5 voci successive avviene con una combinazione di Skip() e Take(), che sono alla base di questo articolo.
Riepilogo
I metodi Skip() e Take() sono molto semplici da usare, ma tuttavia utilissimi in molte situazioni. Come già detto, vengono spesso utilizzati insieme, ma soprattutto il metodo Take() può essere utilizzato anche da solo.