Ցուցակների հետ աշխատելն այն է, ինչ ծրագրավորող լինելն է: Լավ, ես ձգում եմ այն ​​այստեղ, բայց դա այնքան էլ հեռու չէ ճշմարտությունից:

Եթե ​​C#-ը մարդ լիներ, LINQ-ը կլիներ նրա պարանոցային երակը: Ցանկանում եմ ներկայացնել առկա մեթոդներից մի քանիսը, որոնք այնքան էլ հաճախ չեն օգտագործվում։ Առնվազն կրտսեր մշակողների կողմից: Վստահ չեմ, արդյոք դա պայմանավորված է նրանց մասին գիտելիքների պակասով, թե՞ նրանք լուծում են այնպիսի խնդիրներ, որոնք այնքան էլ հաճախ չեն լինում:

Հուսով ենք, որ այն կլինի կարճ և բովանդակալից ընթերցանություն:

OfType<T>()

Զտում է թիրախային տիպի տարրերը ցանկում: Ենթադրենք, որ դուք ունեք պոտենցիալ զրոյական օբյեկտների ցանկ, և ցանկանում եք զտել արժեք ունեցողները: Պարզության համար ես կօգտագործեմ ամբողջ թվեր.

List<int?> numbers = new() { 1, 2, null, 4, null };
var noNulls = numbers.OfType<int>();
// 1, 2, 4

Մեկ այլ պոտենցիալ օգտագործումը կլինի որոշակի դասի օբյեկտների զտումը.

class Animal { }
class Dog : Animal { }
class Cat : Animal { }
List<Animal> animals = new()
{
    new Cat(), new Cat(), new Cat(),
    new Dog(), new Dog()
};
var dogs = animals.OfType<Dog>();

dogs ցուցակը պետք է պարունակի 2 տարր այստեղ:

Aggregate()

Սա fold/reduce-ի LINQ իրականացումն է: Ես այստեղ չեմ բացատրի, թե ինչ է անում fold ֆունկցիան: Եթե ​​չգիտեք, դադարեք կարդալ այս հոդվածը և փնտրեք այն: Պարզ օգտագործում.

List<int> numbers = Enumerable
    .Range(0, 100)
    .ToList();
var sumFrom = 0;
var total = numbers
    .Aggregate(sumFrom, (sum, x) => sum + x);

Նկատի ունեցեք, որ սա միայն ցուցադրական նպատակով է: Այս դեպքում դուք պետք է օգտագործեք Sum() մեթոդը:

SelectMany()

Բազմաթիվ ցուցակները հարթեցնում է մեկ ցուցակի: Դիտարկենք մոդելը.

class Newspapers
{
    string Name;
    List<Article> Articles;
}
class Article
{
    string Title;
    List<Paragraph> Paragraphs;
}
class Paragraph
{
    int WordCount;
}

Ասեք, որ մենք ունենք տարբեր թերթերի ցանկ, և մենք ցանկանում ենք յուրաքանչյուր թերթի բոլոր հոդվածները հավաքել մեկ ցուցակի մեջ.

List<Newspapers> newspapers = new()
{
    new Newspapers(),
    new Newspapers()
};
IEnumerable<Article> articles =
    newspapers.SelectMany(x => x.Articles);

Մենք կարող ենք խորանալ այնքան, որքան ցանկանում ենք: Այսպիսով, մենք կարող ենք հեշտությամբ հարթեցնել թերթերի հոդվածները, քան ստանալ և հարթեցնել պարբերությունները յուրաքանչյուր հոդվածի համար, ինչպես այսպես.

IEnumerable<Paragraph> paragraphs =
    newspapers
    .SelectMany(np => np.Articles, (np, articles) => articles)
    .SelectMany(article => article.Paragraphs);
var totalWordCount = paragraphs.Sum(x => x.WordCount);

Փորձեք դա անել՝ օգտագործելով սովորական Select(), և դուք կհասկանաք այս մեթոդի օգտակարությունը:

Կրկին, հիշեք, որ սա միայն ներկայացման համար է: Դուք պետք է ծաղրեք տվյալները, որպեսզի դա աշխատի, քանի որ ներքին ցուցակները չեն ստեղծվում, և նման ամեն ինչ կանչելը բացառություն կստեղծի:

ToLookup()

Ստեղծում է որոնման աղյուսակ ցուցակից՝ հիմնվելով որպես բանալի տրամադրված հատկության վրա… Ավելի հեշտ է հասկանալ, երբ դուք պարզապես տեսնում եք այն: Դիտարկենք մոդելը.

class Character
{
    public Character(string name, Category catg)
    {
        Name = name;
        Category = catg;
    }
    public string Name;
    public Category Category;
}
enum Category
{
    Knight, Archer, Thief, Mage
}

Եկեք ավելացնենք որոշ կեղծ տվյալներ աշխատելու համար և փոխարկենք դրանք փնտրման.

List<Character> characters = new()
{
    new Character("Arthur", Category.Knight),
    new Character("Lancelot", Category.Knight),
    new Character("Legolas", Category.Archer),
    new Character("Robin Hood", Category.Archer),
    new Character("Garrett", Category.Thief),
    new Character("Gandalf", Category.Mage),
    new Character("Merlin", Category.Mage)
};
ILookup<Category, Character> lookup = characters
    .ToLookup(x => x.Category);

Սա բաժանում է ցանկը՝ հիմնվելով մեր տրամադրած բանալի վրա՝ Category: Պարզության համար ստուգենք որոնման աղյուսակի կառուցվածքը: Ես օգտագործում եմ LinqPad-ը՝ սա անելու համար.

Բավական կոկիկ: Այժմ մենք կարող ենք մուտք գործել որոշակի հավաքածու՝ հիմնվելով բանալիի վրա.

List<Character> knights = lookup[Category.Knight];
List<Character> archers = lookup[Category.Archer];
List<Character> thieves = lookup[Category.Thief];
List<Character> mages = lookup[Category.Mage];

Այնուամենայնիվ, կարևոր նշում. Մի օգտագործեք սա GroupBy()-ի փոխարեն: Կիրառեք այն միայն այն բաների վրա, որոնք արդեն բեռնված են/թվարկված են: ToLookup()-ի կատարումը չի հետաձգվում: Միշտ հիշիր դա:

Ահա և վերջ։ Եթե ​​դուք C# noob եք, համոզվեք, որ ստուգեք ամբողջ գրադարանը: Դա կօգնի ձեզ ավելի մաքուր ծածկագիր գրել: Չնայած այս ֆունկցիոնալության մի մասի նմանակումը լավ է ցուցակների մանիպուլյացիայի ալգորիթմներ կիրառելու համար: Եթե ​​դուք այլևս C# noob չեք, միգուցե այստեղ ինչ-որ բան կար, որի մասին ամբողջովին մոռացել եք: Ես գիտեմ, որ իմ նախկին աշխատանքում ինչ-որ ծածկագիր ունեմ, որը թողել եմ անփոփոխ…

Շնորհակալություն կարդալու համար :)