115. GroupBy Extension method

בהמשך לטיפ היומי של אתמול,

לפעמים במקום למצוא רק לסנן את האיברים שלנו, כך שכל איבר יופיע רק פעם אחת, אנחנו מעוניינים לעשות משהו אחר – לקבץ את האיברים לפי איזושהי תכונה שלהם

למשל, נניח שיש לנו רשימה של אנשים ואנחנו מעוניינים לקבץ אותם לפי הגיל שלהם, כך שלכל גיל נוכל לראות את כל האנשים בגיל זה.

במקום להשתמש בDistinct ולשלב את זה עם שאילתא אחרת, אפשר להשתמש בExtension Method של LINQ ששמו GroupBy:

1
2
IEnumerable<IGrouping<int, Person>> peopleByAge =
people.GroupBy(person => person.Age);

הפונקציה מקבלת delegate שמייצג לפי מה אנחנו מעוניינים לקבץ.

אתם בוודאי שואלים את עצמכם מהו IGrouping<int, Person>? זהוIEnumerable<Person> שיש לו Key שמייצג את מה שהקיבוץ נעשה לפיו.

נוכל לעשות משהו כזה:

1
2
3
4
5
6
7
8
9
10
11
12
foreach (IGrouping<int, Person> currentGroup in peopleByAge)
{
Console.WriteLine("The following are {0} years old:",
currentGroup.Key);
foreach (Person person in currentGroup)
{
Console.WriteLine("{0} {1}",
person.FirstName,
person.LastName);
}
}

יש עוד כמה overloadים שמאפשרים לנו להחליט מה אנחנו מעוניינים לקבץ, וכמובן, איך אפשר בלי, הIEqualityComparer שאיתו אנחנו מעוניינים להשוות איברים.

משהו מגניב שאפשר לעשות: למשל, אנחנו מעוניינים לקטלג אנשים לפי טווח גילאים: 0-12 ילדים, 13-18 נוער, 19 ומעלה מבוגרים. נוכל ליצור IEqualityComparer<int> שמשווה את הגילאים לפי הקריטריונים שכתבתי פה, ולהעביר אותו לקיבוץ:

1
2
3
4
IEqualityComparer<int> ageComparer = new AgeComparer();
IEnumerable<IGrouping<int, Person>> peopleByAge =
people.GroupBy(person => person.Age, ageComparer);

סופ"ש שווה!

שתף