Gruplama, sorguların güçlü özelliklerinden biridir. Gruplama ile bildirilen listedeki aynı veriyi içeren elemanlar bir grup listesi (alt liste) oluşturur. Örneğin müşteriler listemizdeki elemanlar bulundukları şehire göre gruplandırılabilir. Sonuçta herbir şehirdeki müşterilerden oluşan ayrı ayrı listelerimiz olur. Bu şekilde hem grupların eleman sayısı vb. bilgilerine, hem de her bir grubu ayrı ayrı gezerek grubu oluşturan elemanların bilgilerine erişebilir, gruplara göre işlemler gerçekleştirebiliriz.
Gruplanan elemanlar
IGrouping<TKey, TElement> arayüzünü uygulayan bir koleksiyon olarak dönerler. Buradaki T harfi herhangi bir tip anlamındadır.
TKey'in tipi gruplama için kullanılan ortak özelliğin tipine karşılık gelir. Bu arayüz kendisi de
IEnumerable<T> arayüzünü uyguladığı için (
T,
TElement olmak üzere), elemanları tek tek gezilebilir.
TElement ise grup elemanlarının tipini temsil eder.
Şu örneği inceleyin.
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinQLinQ
{
class Program
{
public class Ogrenci
{
public string Adi { get; set; }
public string Soyadi { get; set; }
public int No { get; set; }
public List<int> Yazililar;
}
public static List<Ogrenci> OgrencileriGetir()
{
List<Ogrenci> Ogrenciler = new List<Ogrenci>
{
new Ogrenci {Adi="Kenan", Soyadi="Oran", No=111, Yazililar = new List<int> {97, 72, 60}},
new Ogrenci {Adi="Erhan", Soyadi="Erkanlı", No=112, Yazililar = new List<int> {75, 84, 39}},
new Ogrenci {Adi="Tekin", Soyadi="Uğurlu", No=113, Yazililar = new List<int> {99, 89, 95}},
new Ogrenci {Adi="Mehmet", Soyadi="Emre", No=114, Yazililar = new List<int> {72, 81, 84}},
new Ogrenci {Adi="Ercan", Soyadi="Orak", No=115, Yazililar = new List<int> {97, 89, 82}},
};
return Ogrenciler;
}
static void Main(string[] args)
{
List<Ogrenci> Ogrenciler = OgrencileriGetir();
var ogrenciGruplari =
from ogr in Ogrenciler
group ogr by ogr.Soyadi[0];
// LINQ Yöntem Sözdizimi ile sorgu :
/*
var ogrenciGruplari = Ogrenciler.GroupBy(ogr => ogr.Soyadi[0]);
*/
foreach (var ogrenciGrubu in ogrenciGruplari)
{
Console.WriteLine(ogrenciGrubu.Key);
foreach (var ogr in ogrenciGrubu)
{
Console.WriteLine(" {0}, {1}", ogr.Soyadi, ogr.Adi);
}
}
}
}
}
Çıktı:
O
Oran, Kenan
Orak, Ercan
E
Erkanlı, Erhan
Emre, Mehmet
U
Uğurlu, Tekin
Örnekteki sorgu, öğrencileri soyadlarının ilk harflerine göre gruplandırır ve herbiri
IGrouping<TKey, TElement> arayüzünü uygulayan
IGrouping<char, Ogrenci> tipinde bir grup listesini
IEnumerable<T> biçiminde döndürür. Yani dönen değerin tam tipi
IEnumerable<IGrouping<char, Ogrenci>> olacaktır. Her bir grupta soyadı aynı harfle başlayan (A ile, B ile ... Z ile başlayanlar gibi) öğrencilerin listesi bulunacaktır.
IGrouping<char, Ogrenci> tipindeki
char, grubun anahtarıdır. Bizim örneğimizde anahtar olarak
ogr.Soyadi[0] , yani öğrencinin soyadının 0. harfi (ilk harfi) seçildiğinden tip char (bilindiği gibi string[x] şeklinde bir istek string'in x. karakterini char olarak verir) olmuştur ve her bir grupta (
IGrouping<TKey, TElement> listesinde) gruptakilerin soyadlarının başladığı harfe karşılık gelir. Liste Ogrenci isimli bir sınıfın örneklerini tuttuğundan 2. tip (
TElement) Ogrenci olmuştur.
Dıştaki foreach döngüsü, ogrenciGruplari sorgusunun elemanlarını gezecek ve her bir elemanı
ogrenciGrubu ismiyle temsil edecektir. Dolayısıyla sorgunun türü
IEnumerable<IGrouping<char, Ogrenci>> olduğundan her bir eleman
IGrouping<char, Ogrenci> tipinde bir liste olacaktır.
İçteki döngüden önce grubun anahtarı (örneğimizde gruptaki öğrencilerin hepsinin soyadlarının baş harfi) çıktıya yazdırılıyor.
İçteki döngüde, dıştaki döngünün her dönüşünde seçilen ogrenciGrubu isimli
IGrouping<char, Ogrenci> tipindeki listenin elemanları geziliyor. Bu listenin elemanları Ogrenci tipinde olduğundan döngüdeki seri değişkeni olan
ogr her seferinde bir öğrenciye karşılık gelmekte ve döngü içinde de ogr'nin temsil ettiği
Ogrenci tipindeki nesnenin
Soyadi ve
Adi alanlarının değerleri yazdırılmaktadır.
Bu örnekteki sorguyu devam ettirmek isterseniz
group cümleciğine
into ile daha sonraki işlemlerde kullanılmak üzere bir tanımlayıcı değişken eklemeniz gerekir.
Üstteki örneğin
where ve
orderby kullanılmış şekli şöyle olur.
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinQLinQ
{
class Program
{
public class Ogrenci
{
public string Adi { get; set; }
public string Soyadi { get; set; }
public int No { get; set; }
public List<int> Yazililar;
}
public static List<Ogrenci> OgrencileriGetir()
{
List<Ogrenci> Ogrenciler = new List<Ogrenci>
{
new Ogrenci {Adi="Kenan", Soyadi="Oran", No=111, Yazililar = new List<int> {97, 72, 60}},
new Ogrenci {Adi="Erhan", Soyadi="Erkanlı", No=112, Yazililar = new List<int> {75, 84, 39}},
new Ogrenci {Adi="Tekin", Soyadi="Uğurlu", No=113, Yazililar = new List<int> {99, 89, 95}},
new Ogrenci {Adi="Mehmet", Soyadi="Emre", No=114, Yazililar = new List<int> {72, 81, 84}},
new Ogrenci {Adi="Ercan", Soyadi="Orak", No=115, Yazililar = new List<int> {97, 89, 82}},
};
return Ogrenciler;
}
static void Main(string[] args)
{
List<Ogrenci> Ogrenciler = OgrencileriGetir();
var ogrenciGruplari =
from ogr in Ogrenciler
group ogr by ogr.Soyadi[0] into basHarfGrubu
where basHarfGrubu.Count() > 1
orderby basHarfGrubu.Key
select basHarfGrubu;
// LINQ Yöntem Sözdizimi ile sorgu :
/*
var ogrenciGruplari = Ogrenciler.GroupBy(ogr => ogr.Soyadi[0])
.Where(basHarfGrubu => basHarfGrubu.Count() > 1)
.OrderBy(basHarfGrubu => basHarfGrubu.Key);
*/
foreach (var ogrenciGrubu in ogrenciGruplari)
{
Console.WriteLine(ogrenciGrubu.Key);
foreach (var ogr in ogrenciGrubu)
{
Console.WriteLine("{0}, {1}", ogr.Soyadi, ogr.Adi);
}
}
Console.ReadKey();
}
}
}
Çıktı:
Çıktı :
E
Erkanlı, Erhan
Emre, Mehmet
O
Oran, Kenan
Orak, Ercan
Üstte bahsedilen tanımlayıcı değişken örnekte "into" ifadesinin yanındaki "basHarfGrubu" ifadesidir.
Örnekte görüldüğü gibi sorgunun 2. satırında grubun "basHarfGrubu" isimli bir değişkene atanması ve eleman sayısı 1'den büyük olan grupların seçilmesi, grupların grup anahtarına (IGrouping<TKey, TElement> biçiminin Key özelliği) göre (örneğimizde soyadların baş harfleri yani harfe göre) sıralanması bildirilmiş.