Sveicināti,
Jau kādu brīdi izmantoju LINQ veicot datu atlasi, grupēšanu, kārtošanu un tam līdzīgas lietas. Šoreiz gribēju apskatīt vienu klasisko uzdevuma atrisinājumu izmantojot LINQ iespējas.
Tātad, man ir noteikts importa fails. Parasts teksta fails, kurš sastāv no rindām, rindu saturs tiek dalīts ar sadalītāju(manā gadījumā – Tab). Pieņemsim, ka mums nav svarīgs datu ielasīšanas process, bet gan rindu apstrāde.
Piemērs,
var lines = new[]{ "Andrejs Mamontovs\t28\tmale", "Ivars Āriņš\t25\tmale" };
Atmiņā ir ielasīti divi ieraksti. Pagrūti saprast, ko tad šīs rindiņas satur. Sāksim ar atšifrējumu. Katra rinda sadalīta uz trim daļām (Vārds Uzvārds, vecums, dzimums). Tātad, rindiņa ir jādala.
foreach (var line in lines)
{
var parts = line.Split('\t');
}
Vērtība ar indeksu nulle būs Vārds Uzvārds. Vērtība ar indeksu viens būs vecums. Vērtība ar indeksu divi būs dzimums.
Console.WriteLine("Vārds Uzvārds: {0}", parts[0]);
Console.WriteLine("Vecums: {0}", parts[1]);
Console.WriteLine("Dzimums: {0}", parts[2]);
Iespējams šis ir pats izplatītākais veids, kā praksē tiek apstrādāti dati, bet man tāds nepatīk. Uzturēšanas ziņā neērti. Es vēlos izveidot noteiktu struktūru, ar atšifrējumu kas ir kas.
Pirmkārt, izveidoju pārskaitījumu ar lauku nosaukumu.
public enum LineTags
{
FullName,
Age,
Gender
}
Lauku apstrādes kodu var tagad pārrakstīt, lai tiek izmantots pārskaitījums
Console.WriteLine("Vārds Uzvārds: {0}", parts[(int)LineTags.FullName]);
Console.WriteLine("Vecums: {0}", parts[(int)LineTags.Age]);
Console.WriteLine("Dzimums: {0}", parts[(int)LineTags.Gender]);
Šinī gadījumā esam atteikušies no indeksiem, bet nav vel ideāli, ir nepieciešams pārskaitījumu tipu pārveidot uz tipu Integer. Šeit būtu pareizi izmantot Generic iespējas, lai simbolu kopas meklēšana notiktu pēc LineTags pārskaitījuma. Un šeit var noderēt LINQ konstrukcijas.
var parts = line.Split('\t').Select(
(s, index) => new { Tag = (LineTags)index, Substring = s }).ToDictionary(
c => c.Tag, c => c.Substring);
Vispirms ar Split sadalām rindu uz sastāvdaļām. Ar metodi Select visi masīva elementi (String tips) tiek pārveidoti anonīmajā tipā. Tips satur divus laukus (Tag un Substring). Tag lauks tiek aizpildīts ar ieraksta indeksu. Ieraksta indekss ir Integer tips, to varam bez problēmām pārveidot par LineTags tipu. Substring lauks tiek aizpildīts ar oriģinālo simbolu kopu. Pēc šīs pārveidošanas iegūstam sarakstu ar jauno tipu. Noslēgumā jauno sarakstu pārveidot par vārdnīcu, kurā kā indeksi tiek izmantots tips LineTags.
Modificējam datu iegūšanas kodu
Console.WriteLine("Vārds Uzvārds: {0}", parts[LineTags.FullName]);
Console.WriteLine("Vecums: {0}", parts[LineTags.Age]);
Console.WriteLine("Dzimums: {0}", parts[LineTags.Gender]);
Kā redzam tikām vaļā no tipa pārveidošanas uz Integer. Kā arī tagad mums ir grūtāk kļūdīties atlasot datus. Šāds paņemies protams nebūt nav tas ātrākais, starpība ir aptuveni 5.5x reizes. Ir testēts uz aptuveni 100000 ierakstu. Ja parastā apstrāde aizņēma ~100ms, tad gadījumā ar LINQ bija ~600ms. Protams, ir jāskatās pēc situācijas. Bet noteikti šis gadījums ir spējīgs dzīvot.
Cerams ka noderēs!
Posted
Apr 01 2009, 09:33 AM
by
andrejs.mamontovs