๐Ÿ’ป Programming Language/C#

42. LINQ ์„ธ๋ถ€ ๋ฌธ๋ฒ•

S.Honey 2022. 4. 8. 09:17

๋‘ ๊ฐœ์˜ from ์ ˆ์„ ์ด์šฉํ•œ LINQ ๋ฌธ

using System.Collections;



namespace LINQEx
{
    class MemberScore
    {
        public string Name { get; set; }
        public int[] Score { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MemberScore[] ms =
            {
                new MemberScore(){Name="ํ™๊ธธ๋™",Score=new int[]{30, 42, 67 } },
                new MemberScore(){Name="์ฒญ๊ธธ๋™",Score=new int[]{88, 45, 87 } },
                new MemberScore(){Name="๋…น๊ธธ๋™",Score=new int[]{55, 66, 77 } },
                new MemberScore(){Name="ํ‘๊ธธ๋™",Score=new int[]{90, 80, 70 } },
                new MemberScore(){Name="๋ฐฑ๊ธธ๋™",Score=new int[]{99, 88, 30 } }
            };

            var members = from m in ms
                          from s in m.Score
                          where s < 60
                          orderby s, m.Name
                          select new {m.Name, FScore = s};

            foreach (var m in members)
            {
                Console.WriteLine($"์ด๋ฆ„ : {m.Name} Fํ•™์  ์„ฑ์  : {m.FScore}");
            }
        }
    }
}
Output

์ด๋ฆ„ : ๋ฐฑ๊ธธ๋™ Fํ•™์  ์„ฑ์  : 30
์ด๋ฆ„ : ํ™๊ธธ๋™ Fํ•™์  ์„ฑ์  : 30
์ด๋ฆ„ : ํ™๊ธธ๋™ Fํ•™์  ์„ฑ์  : 42
์ด๋ฆ„ : ์ฒญ๊ธธ๋™ Fํ•™์  ์„ฑ์  : 45
์ด๋ฆ„ : ๋…น๊ธธ๋™ Fํ•™์  ์„ฑ์  : 55
  • LINQ ๋ฌธ ๋‚ด ๋‘๋ฒˆ์งธ from์ ˆ from s in m.Score ๋™์ž‘์€ ๊ฐ ์ธ์Šคํ„ด์Šค ๋ณ„ Score๋ฐฐ์—ด๋‚ด์—์„œ ํ•œ๊ฐœ์˜ ์ ์ˆ˜์”ฉ ํ™•์ธ์„ ์ง„ํ–‰ํ•จ.

Group By ์ ˆ


group by ํ˜•์‹
group X by Y into Z
X๋Š” from ์ ˆ์—์„œ ๊ฐ€์ ธ์˜จ ๋ฒ”์œ„๋ณ€์ˆ˜
Y๋Š” ๋ถ„๋ฅ˜๊ธฐ์ค€
Z๋Š” ๊ทธ๋ฃน๋ณ€์ˆ˜

Group By ์ ˆ ์‚ฌ์šฉ์˜ˆ์ œ ์ฝ”๋“œ

using System.Collections;

namespace LINQEx
{
    class Member
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Member[] m =
            {
                new Member(){Name = "๊ฐ•ํ˜ธ๋™", Age = 42},
                new Member(){Name = "์†ํฅ๋ฏผ", Age = 31},
                new Member(){Name = "๊น€์—ฐ์•„", Age = 22},
                new Member(){Name = "์žฅ๋ฏธ๋ž€", Age = 35},
                new Member(){Name = "์ด๋งŒ๊ธฐ", Age = 49}
            };

            var Group = from member in m
                        group member by member.Age > 35 into OB
                        select new { groupkey = OB.Key, members = OB };

            foreach (var member in Group)
            {
                if(member.groupkey)
                {
                    Console.WriteLine("<35์„ธ ์ดˆ๊ณผ ๋ฉค๋ฒ„>");
                    foreach(var member2 in member.members)
                    {
                        Console.WriteLine($"์ด๋ฆ„ : {member2.Name} ๋‚˜์ด : {member2.Age}");
                    }
                }
                else
                {
                    Console.WriteLine("<35์„ธ ์ดํ•˜ ๋ฉค๋ฒ„>");
                    foreach (var member2 in member.members)
                    {
                        Console.WriteLine($"์ด๋ฆ„ : {member2.Name} ๋‚˜์ด : {member2.Age}");
                    }
                }
            }
        }
    }
}
Output

<35์„ธ ์ดˆ๊ณผ ๋ฉค๋ฒ„>
์ด๋ฆ„ : ๊ฐ•ํ˜ธ๋™ ๋‚˜์ด : 42
์ด๋ฆ„ : ์ด๋งŒ๊ธฐ ๋‚˜์ด : 49
<35์„ธ ์ดํ•˜ ๋ฉค๋ฒ„>
์ด๋ฆ„ : ์†ํฅ๋ฏผ ๋‚˜์ด : 31
์ด๋ฆ„ : ๊น€์—ฐ์•„ ๋‚˜์ด : 22
์ด๋ฆ„ : ์žฅ๋ฏธ๋ž€ ๋‚˜์ด : 35
[ํ•ด๋‹น ์˜ˆ์ œ์ฝ”๋“œ LINQ ๊ตฌ๋ฌธ]
var Group = from member in m
    group member by member.Age > 35 into OB
    select new { groupkey = OB.Key, members = OB };
  • 35์„ธ ์ดˆ๊ณผ์ธ ๊ฒฝ์šฐ๋ฅผ OB๋กœ ๊ทธ๋ฃนํ•‘์„ ์ง„ํ–‰.
  • OB์— ํฌํ•จ๋œ ๋ฐ์ดํ„ฐ๋“ค์˜ groupkey = true ๋กœ ์ €์žฅ. false ์ธ๊ฒฝ์šฐ์—๋Š” 35์„ธ์ดํ•˜์ธ ์ธ์Šคํ„ด์Šค๋“ค์ด ์ €์žฅ๋จ.
  • ์ด๋•Œ member ์—๋Š” ๊ฐ๊ฐ์˜ ์ธ์Šคํ„ด์Šค๋“ค์ด ํ• ๋‹น๋จ. (๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์ €์žฅ๋˜์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๊ฐ€ ์•„๋‹˜ = LINQ๋ฌธ ๋‚ด์—์„œ๋งŒ ์œ ํšจ)
key data
true {Name = "๊ฐ•ํ˜ธ๋™", Age = 42}, {Name = "์ด๋งŒ๊ธฐ", Age = 49}
false {Name = "์†ํฅ๋ฏผ", Age = 31}, {Name = "๊น€์—ฐ์•„", Age = 22},{Name = "์žฅ๋ฏธ๋ž€", Age = 35}

์กฐ์ธ(Join)

  • ์กฐ์ธ(join) : ์„œ๋กœ ๋‹ค๋ฅธ ๋‘๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•ฉ์น˜๋Š” ๊ฒƒ, ์™„์ „ํžˆ ๋‹ค๋ฅธ๊ฒƒ์€ ์•„๋‹ˆ๊ณ  ์ผ์น˜ํ•˜๋Š” ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ํ•ฉ์นจ
    - `๋‚ด๋ถ€์กฐ์ธ(inner join)` : ๋‘ ๋ฐ์ดํ„ฐ์˜ ์ผ์น˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋“ค๋งŒ ํ•ฉ์ณ์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ.
    - `์™ธ๋ถ€์กฐ์ธ(outer join)` : ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚ด๋ถ€ ์กฐ์ธ๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ, ์กฐ๊ฑด์ด ์ผ์น˜ํ•˜์ง€ ์•Š๋”๋ผ๋„ ๊ธฐ์ค€๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜๋„ ๋ˆ„๋ฝ์‹œํ‚ค์ง€ ์•Š๊ณ , ๊ทธ๋Œ€๋กœ ์ถ”์ถœํ•˜์—ฌ ๋นˆ ๋ฐ์ดํ„ฐ๋ฅผ ์ฑ„์›Œ์„œ ํ†ตํ•ฉํ•˜๋Š” ๋ฐฉ์‹ - ์™ธ๋ถ€์กฐ์ธ์—์„œ ๊ธฐ์ค€๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋–ค๊ฒƒ์ด๋ƒ์— ๋”ฐ๋ผ ๋ง๋ถ™๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ฌ๋ผ์ง. - ๊ธฐ์ค€๋ฐ์ดํ„ฐ์˜ ๋‚จ์€ ์ผ์น˜ํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ์™€ ์ผ์น˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๊ฒƒ. - ์—ฌ๊ธฐ์„œ ๋‚˜์˜จ ๊ฐœ๋…์ด `์™ผ์ชฝ์กฐ์ธ(left join)`, `์˜ค๋ฅธ์ชฝ์กฐ์ธ(right join)`, `์™„์ „์กฐ์ธ(full-outer join)`์ด๋‹ค.

  • LINQ์—์„œ๋Š” ์™ผ์ชฝ ์กฐ์ธ(left join)๋งŒ์„ ์ง€์›ํ•˜๊ณ , ์™ ๋งŒํ•ด์„œ๋Š” ์™ผ์ชฝ์กฐ์ธ๋งŒ์œผ๋กœ ํ•ด๊ฒฐ๊ฐ€๋Šฅํ•˜๋‹ค.

์กฐ์ธ(join) ์„ ์–ธ ํ˜•์‹

    from a in A // ๊ธฐ์ค€๋ฐ์ดํ„ฐ 
    join b in B on a.xxx equals b.xxx // ์กฐ์ธ๋ฐ์ดํ„ฐ ๋ฐ ์กฐ์ธ์„ ์–ธ

๋‚ด๋ถ€์กฐ์ธ(Inner Join) ์‚ฌ์šฉ ์ฝ”๋“œ ์˜ˆ์ œ


using System.Collections;

namespace LINQEx
{

    class Student
    {
        public string name { get; set; }
        public int age { get; set; }
    }

    class Score
    {
        public string name { get; set; }
        public int math { get; set; }
        public int english { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Student[] studentList =
            {
                new Student(){name = "๊น€๋ง๋˜ฅ", age = 21},
                new Student(){name = "๋‚˜๋ง๋˜ฅ", age = 22},
                new Student(){name = "๋ฐ•๋ง๋˜ฅ", age = 23},
                new Student(){name = "์ด๋ง๋˜ฅ", age = 24},
                new Student(){name = "์ตœ๋ง๋˜ฅ", age = 25},
            };

            Score[] scoreList =
            {
                new Score(){name = "๊น€๋ง๋˜ฅ", math = 98, english =77},
                new Score(){name = "๋‚˜๋ง๋˜ฅ", math = 88, english =66},
                new Score(){name = "๊ฐ•๋ง๋˜ฅ", math = 69, english =99},
                new Score(){name = "์ด๋ง๋˜ฅ", math = 79, english =88},
                new Score(){name = "์˜ค๋ง๋˜ฅ", math = 54, english =55},
            };

            var Students = from student in studentList
                           join score in scoreList on student.name equals score.name
                           select new
                           {
                               Name = student.name,
                               Age = student.age,
                               Math = score.math,
                               English = score.english,
                           };

            foreach (var s in Students)
            {
                Console.WriteLine($"์ด๋ฆ„ : {s.Name}, ๋‚˜์ด : {s.Age}์„ธ, ์ˆ˜ํ•™ : {s.Math}์ , ์˜์–ด : {s.English}์ ");
            }
        }
    }
}
Output

์ด๋ฆ„ : ๊น€๋ง๋˜ฅ, ๋‚˜์ด : 21์„ธ, ์ˆ˜ํ•™ : 98์ , ์˜์–ด : 77์ 
์ด๋ฆ„ : ๋‚˜๋ง๋˜ฅ, ๋‚˜์ด : 22์„ธ, ์ˆ˜ํ•™ : 88์ , ์˜์–ด : 66์ 
์ด๋ฆ„ : ์ด๋ง๋˜ฅ, ๋‚˜์ด : 24์„ธ, ์ˆ˜ํ•™ : 79์ , ์˜์–ด : 88์ 
  • Student ์ธ์Šคํ„ด์Šค์™€ Score ์ธ์Šคํ„ด์Šค ๋ฐ์ดํ„ฐ ๋‚ด ์ผ์น˜ํ•˜๋Š” ์ด๋ฆ„์ด ๊น€๋ง๋˜ฅ, ๋‚˜๋ง๋˜ฅ, ์ด๋ง๋˜ฅ์ธ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ธฐ์ค€๋ฐ์ดํ„ฐ๋Š” Student ์ธ์Šคํ„ด์Šค ๋‚ด ๋ฐ์ดํ„ฐ๋กœ ํ•˜์˜€์œผ๋ฉฐ, ๋‚ด๋ถ€์กฐ์ธ ์ด๋ฏ€๋กœ ์ผ์น˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋งŒ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์™ธ๋ถ€์กฐ์ธ(Outer Join)


์™ธ๋ถ€์กฐ์ธ ํ˜•์‹
    from a in A
    join b in B on a.xxx equals b.xxx into temp 
    // ์—ฌ๊ธฐ๊นŒ์ง€๋Š” ๋‚ด๋ถ€์กฐ์ธ๊ณผ ๋น„์Šทํ•œ ๋™์ž‘์„ํ•ด์„œ ๋ฐ˜ํ™˜๊ฒฐ๊ณผ๋ฅผ temp์— ์ €์žฅ
    from b in temp.DefaultEmpty(new B() {empty = ""})
    // temp์—์„œ ๋น„์–ด์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ b์—์„œ์˜ ์†์„ฑ๊ฐ’์œผ๋กœ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ์ƒ์„ฑ.

์™ธ๋ถ€์กฐ์ธ(Outer Join) ์‚ฌ์šฉ ์ฝ”๋“œ ์˜ˆ์ œ

using System.Collections;

namespace LINQEx
{

    class Student
    {
        public string name { get; set; }
        public int age { get; set; }
    }

    class Score
    {
        public string name { get; set; }
        public int math { get; set; }
        public int english { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Student[] studentList =
            {
                new Student(){name = "๊น€๋ง๋˜ฅ", age = 21},
                new Student(){name = "๋‚˜๋ง๋˜ฅ", age = 22},
                new Student(){name = "๋ฐ•๋ง๋˜ฅ", age = 23},
                new Student(){name = "์ด๋ง๋˜ฅ", age = 24},
                new Student(){name = "์ตœ๋ง๋˜ฅ", age = 25},
            };

            Score[] scoreList =
            {
                new Score(){name = "๊น€๋ง๋˜ฅ", math = 98, english =77},
                new Score(){name = "๋‚˜๋ง๋˜ฅ", math = 88, english =66},
                new Score(){name = "๊ฐ•๋ง๋˜ฅ", math = 69, english =99},
                new Score(){name = "์ด๋ง๋˜ฅ", math = 79, english =88},
                new Score(){name = "์˜ค๋ง๋˜ฅ", math = 54, english =55},
            };

            var Students = from student in studentList
                           join score in scoreList on student.name equals score.name into temp
                           from score in temp.DefaultIfEmpty(new Score() { math = 100, english = 100 })
                           select new
                           {
                               name = student.name,
                               age = student.age,
                               math = score.math,
                               english = score.english,
                           };

            foreach (var student in Students)
            {
                Console.WriteLine(student);
            }
        }
    }
}
Output

{ name = ๊น€๋ง๋˜ฅ, age = 21, math = 98, english = 77 }
{ name = ๋‚˜๋ง๋˜ฅ, age = 22, math = 88, english = 66 }
{ name = ๋ฐ•๋ง๋˜ฅ, age = 23, math = 100, english = 100 }
{ name = ์ด๋ง๋˜ฅ, age = 24, math = 79, english = 88 }
{ name = ์ตœ๋ง๋˜ฅ, age = 25, math = 100, english = 100 }