Giriş
İmzası şöyle
Elimizde şöyle bir liste olsun
Yukarıdaki örnekten farklı olarak Key.Port gibi anahtarın alt parçalarına erişiyoruz. Elimizde Trip nesnesinden oluşuna bir nesne olsun
Elimizde iki tane dizi olsun.
Gruplama yapıldıktan sonra elimizde bir multimap varmış gibi düşünülebilir. Bu multimap aynı IEnumerable gibi metodlar sağlar.
Örnek - en küçük olanı seçmek
Elimizde şöyle bir sınıf olsun
İki listeyi birleştirip en büyük olanı seçmek için şöyle yaparız.
Elimizde şöyle bir liste olsun.
Bir diğer örnek MoreLinq'te Batch ismiyle geçiyor. Elimizde şöyle bir liste olsun
GroupBy bir multimap yani Lookup döner. İçi şuna benzer.
İmzası şöyle
public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector
)
GroupBy ile Key ve Count KullanımıElimizde şöyle bir liste olsun
"FF"
"ABC"
"CC"
"FF"
"FF"
Eğer bu listede FF değerine sahip kaç eleman var diye öğrenmek istersek şöyle yaparız.var f = Rank.GroupBy(x => x)
.Select(g => new { Value = g.Key, Count = g.Count() })
.Where(s => s.Value == "FF");
Bu durumda şu sonucu alırız.value: ff
count: 3
GroupBy ile Key Nesnesinin Alanlarına ErişmekYukarıdaki örnekten farklı olarak Key.Port gibi anahtarın alt parçalarına erişiyoruz. Elimizde Trip nesnesinden oluşuna bir nesne olsun
public class Trip
{
public string Port {get;set;}
public string TripId {get;set;}
public string StatusId {get;set;}
}
Bu listeyi TripId, ve Port alanlarına göre gruplayalım. Daha sonra sayısı >1 olan grupları seçelim. Yani aynı yere birden fazla yapılan seyahatleri seçiyoruz.YourList
.GroupBy(c => new { c.TripId, c.Port })
.Where(grp => grp.Count() > 1)
.Select(grp => new { Port = grp.Key.Port, TripId = grp.Key.TripId });
Dictonary Haline ÇevirmekElimizde iki tane dizi olsun.
{"A", "C", "A", "A", "B", "B", "A", "A" }
{ 1, 1, 2, 3, 1, 10, 5, 7 }
İlk diziye göre gruplamak için şöyle yaparız.var list = first.Zip(second, (f, s) => new { First = f, Second = s });
Dictionary<string, int[]> d = list.GroupBy(i => i.First)
.ToDictionary(k => k.Key, v => v.Select(val => val.Second)
.ToArray()
);
Çıktı olarak şunu alırız.A: { 1, 2, 3, 5, 7 }
B: { 1, 10 }
C: { 1 }
Gruplanmış Listedeki Elemanlara ErişmekGruplama yapıldıktan sonra elimizde bir multimap varmış gibi düşünülebilir. Bu multimap aynı IEnumerable gibi metodlar sağlar.
Örnek - en küçük olanı seçmek
Elimizde şöyle bir sınıf olsun
class Member
{
public string CategoryId { get; set; }
public string MemberName { get; set; }
public int Distance { get; set; }
}
Bu sınıftan oluşan şöyle bir liste olsun .var list = new List<Member>();
list.Add(new { CategoryId = "01", MemberName="andy" Distance=3});
list.Add(new { CategoryId = "02", MemberName="john" Distance=5});
list.Add(new { CategoryId = "01", MemberName="mathew" Distance=7});
list.Add(new { CategoryId = "03", MemberName="bakara" Distance=2});
Her grubun en kısa mesafeye sahip elemanını istersek şu çıktıyı bekleriz.{ CategoryId = "01", MemberName="andy" Distance=3};
{ CategoryId = "02", MemberName="john" Distance=5};
{ CategoryId = "03", MemberName="bakara" Distance=2};
Dolayısıyla OrderBy ve ardından First çağırırsak beklediğimiz çıktıyı alırız.var grouped = list.GroupBy(item => item.CategoryId);
var shortest = grouped.Select(grp => grp.OrderBy(item => item.Distance).First());
Örnek - en büyük olanı seçmekİki listeyi birleştirip en büyük olanı seçmek için şöyle yaparız.
var result = item1.Union(item2)
.GroupBy(e => e.id)
.Select(g =>
g.OrderByDescending(e => e.Rating).First()
);
ÖrnekElimizde şöyle bir liste olsun.
BuildingID | Ticket | Amount |CustomerID | BuildingName
10 | 001 | 50 | 1 | JP Building
11 | 002 | 45 | 1 | Tiskon
52 | 452 | 35 | 2 | Lalit
65 | 568 | 78 | 2 | Tuilp
41 | 121 | 12 | 1 | BK Trp
Multimap'in value listesini başka nesneye çevirmek için şöyle yaparız.var objCustomerBuildingMappingResult = listTickets.GroupBy(l => l.CustomerID)
.Select(grp => new CustomerBuildingMapping
{
CustomerID = grp.Key,
LeadId = long.Parse(grp.Key) + 1000,
BuildingInfo = grp.Select(l => new BuildingInfo {
BuildingID = l.BuildingID,
TicketNumber = l.Ticket,
Amount = l.Amount,
BuildingName = l.BuildingName
}).ToList(),
}).ToList();
Çıktı olarak şunu alırız.LeadID 1001
CustomerID 1
BuildingInfo
BuildingID | Ticket | Amount | BuildingName
10 | 001 | 50 | JP Building
11 | 002 | 45 | Tiskon
41 | 121 | 12 | BK Trp
LeadID 1002
CustomerID 2
BuildingInfo
BuildingID | Ticket | Amount | BuildingName
52 | 452 | 35 | Lalit
65 | 568 | 78 | Tulip
3. DiğerBir diğer örnek MoreLinq'te Batch ismiyle geçiyor. Elimizde şöyle bir liste olsun
var listOfStrings = new List<string>
{
"String 1",
"String 2",
"String 3",
"String 4",
"String 5",
"String 6"
};
Bu listeyi 3'lük kümeler halinde bölerek işlemek istersek şöyle yaparız.Önce Batch isimli bir metod yazarız. İlk select listemizi yeni bir nesne ile sarmalar. GroupBy sarmalayan nesneleri 3'lük olacak şekilde kümeler. Son select ise gruplanmış ancak sarmalanmış olan nesneleri açarak sadece kendi nesnemizi içeren 3'lük liste döndürür.public static class EnumerableExtensions
{
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> items,
int maxItems)
{
return items.Select((item, inx) => new { item, inx })
.GroupBy(x => x.inx / maxItems)
.Select(g => g.Select(x => x.item));
}
}
Daha sonra bu metodumuzu şöyle çağırırız.foreach (var batch in listOfStrings.Batch(3))
{
// batch is an IEnumerable<T>, and will have 3 items.
foreach (var item in batch)
{
}
}
GroupBy'ın İçi NasıldırGroupBy bir multimap yani Lookup döner. İçi şuna benzer.
Func<TSource, TElement> elementSelector = x => x;
<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
foreach (TSource tSource in source)
{
TKey key = keySelector(tSource);
// simplified pseudo-code
if (!lookup.Contains(key))
lookup.Add(new Grouping(key));
lookup[key].Add(elementSelector(tSource));
}
foreach(IGrouping<TKey, TElement> grouping in lookup)
yield return grouping;
Hiç yorum yok:
Yorum Gönder