লিনকুতে গ্রুপ করুন


1061

ধরা যাক আমাদের মতো ক্লাস থাকলে:

class Person { 
    internal int PersonID; 
    internal string car; 
}

এখন আমি এই শ্রেণীর একটি তালিকা আছে: List<Person> persons;

এখন এই তালিকার একাধিক উদাহরণ থাকতে পারে PersonIDউদাহরণস্বরূপ:

persons[0] = new Person { PersonID = 1, car = "Ferrari" }; 
persons[1] = new Person { PersonID = 1, car = "BMW"     }; 
persons[2] = new Person { PersonID = 2, car = "Audi"    }; 

আমি কীভাবে কোনও গ্রুপে গ্রুপ করে PersonIDতার কাছে থাকা সমস্ত গাড়িগুলির তালিকা পেতে পারি?

উদাহরণস্বরূপ, প্রত্যাশিত ফলাফল হবে

class Result { 
   int PersonID;
   List<string> cars; 
}

সুতরাং গ্রুপিংয়ের পরে, আমি পাবেন:

results[0].PersonID = 1; 
List<string> cars = results[0].cars; 

result[1].PersonID = 2; 
List<string> cars = result[1].cars;

আমি এ পর্যন্ত যা করেছি তা থেকে:

var results = from p in persons
              group p by p.PersonID into g
              select new { PersonID = g.Key, // this is where I am not sure what to do

কেউ দয়া করে আমাকে সঠিক দিকে নির্দেশ করতে পারেন?


1
সেখানে সহ অন্য একটি উদাহরণ Countএবং Sumএখানে stackoverflow.com/questions/3414080/...
বিকাশকারী

@ মার্টিন কলম্যান: আমি ক্রিস ওয়ালশের সাথে একমত। সম্ভবত কোনও অ্যাপের ওপির "ব্যক্তি (গুলি)" শ্রেণি (টেবিল) রয়েছে এমন ইতিমধ্যে একটি "" সাধারণ "" "ব্যক্তি (গুলি)" শ্রেণি (টেবিল) রয়েছে যা ইউএসयू রয়েছে। বৈশিষ্ট্য / কলাম (যেমন নাম, লিঙ্গ, ডিওবি)। ওপি'র "ব্যক্তি (গুলি)" শ্রেণি (ছক) হ'ল "সাধারণ" "" ব্যক্তি (গুলি) "শ্রেণির (টেবিল) এর একটি শিশু শ্রেণি (টেবিল) হবে (যেমন একটি" অর্ডার আইটেম) গুলি ক্লাস (সারণী) ) বনাম একটি "আদেশ (গুলি)" শ্রেণি (সারণী))। ওপি সম্ভবত প্রকৃত নামটি ব্যবহার করবে না যদি এটি তার "'সাধারণ' '" ব্যক্তি (গুলি) "শ্রেণি (টেবিল) এর মতো একই স্কোপে থাকে এবং / বা এই পোস্টের জন্য এটি সরল করে তুলেছিল।
টম

উত্তর:


1731

অবশ্যই - আপনি মূলত চান:

var results = from p in persons
              group p.car by p.PersonId into g
              select new { PersonId = g.Key, Cars = g.ToList() };

বা অ-কোয়েরি এক্সপ্রেশন হিসাবে:

var results = persons.GroupBy(
    p => p.PersonId, 
    p => p.car,
    (key, g) => new { PersonId = key, Cars = g.ToList() });

মূলত গোষ্ঠীর বিষয়বস্তু (যখন হিসাবে দেখা হবে IEnumerable<T>) p.carপ্রদত্ত কীটির জন্য প্রজেকশনটিতে ( এই ক্ষেত্রে) উপস্থিত মানগুলি ছিল তার ক্রম ।

কীভাবে GroupByকাজ করে তার আরও তথ্যের জন্য , বিষয়টিতে আমার এডুলিনক পোস্টটি দেখুন ।

(আমি নতুন নামকরণ করে থাকেন PersonIDকরার PersonIdউপরে, অনুসরণ করার .NET নামকরণ নিয়মাবলী ।)

বিকল্পভাবে, আপনি এটি ব্যবহার করতে পারেন Lookup:

var carsByPersonId = persons.ToLookup(p => p.PersonId, p => p.car);

তারপরে আপনি প্রতিটি ব্যক্তির জন্য গাড়িগুলি খুব সহজেই পেতে পারেন:

// This will be an empty sequence for any personId not in the lookup
var carsForPerson = carsByPersonId[personId];

11
@ জোন স্কিটে যদি আমি নামের মতো আরও একটি সম্পত্তি যুক্ত করতে চাই তবে
ব্যবহারকারী 123456

22
@ মোহাম্মদ: তারপরে আপনি এটিকে বেনামে টাইপ করুন।
জন স্কিটি

7
@ ব্যবহারকারী 123456 এখানে দ্বারা গ্রুপের একটি ভাল ব্যাখ্যা এখানে রয়েছে, এটি একটি সংমিশ্রিত কী দ্বারা গোষ্ঠীকরণের একটি উদাহরণও অন্তর্ভুক্ত করেছে: কীভাবে: গ্রুপ ক্যোয়ারী ফলাফল (সি # প্রোগ্রামিং গাইড)
ম্যাথিউ ডিয়েপম্যান

14
@ মোহাম্মদ আপনি এর মতো কিছু করতে পারেন .GroupBy(p => new {p.Id, p.Name}, p => p, (key, g) => new { PersonId = key.Id, PersonName = key.Name, PersonCount = g.Count()})এবং আপনি প্রত্যেক ব্যক্তির জন্য একটি আইডি, নাম এবং বিভিন্ন সংখ্যক ঘটনার সাথে সংঘটিত সমস্ত লোককে পাবেন।
ক্রিস

11
@ কামে: আমি ইচ্ছাকৃতভাবে। নেট নামকরণ কনভেনশনগুলি অনুসরণ করছিলাম, ওপির নামগুলি মূলত ঠিক করেছিলাম। উত্তরে তা পরিষ্কার করে দেবে।
জন স্কিটি

52
var results = from p in persons
              group p by p.PersonID into g
              select new { PersonID = g.Key,
                           /**/car = g.Select(g=>g.car).FirstOrDefault()/**/}


32

আপনি এটি ব্যবহার করে দেখতে পারেন:

var results= persons.GroupBy(n => new { n.PersonId, n.car})
                .Select(g => new {
                               g.Key.PersonId,
                               g.Key.car)}).ToList();

এটি ভুল যে একই তালিকাটি গোষ্ঠীভুক্ত নয় তা ফেরত দেয়
বিকাশ গুপ্ত

এটি কাজ, আমি মনে করি কিছু অনুপস্থিত কারণ এটি আপনার কোডে কাজ করে না।
শুভ সরকার

28

চেষ্টা

persons.GroupBy(x => x.PersonId).Select(x => x)

অথবা

আপনার তালিকায় কোনও ব্যক্তি পুনরাবৃত্তি করছে কিনা তা পরীক্ষা করে দেখুন

persons.GroupBy(x => x.PersonId).Where(x => x.Count() > 1).Any(x => x)

13

আমি কোয়েরি সিনট্যাক্স এবং পদ্ধতি সিনট্যাক্স সহ একটি ওয়ার্কিং কোড নমুনা তৈরি করেছি। আমি আশা করি এটি অন্যকে সাহায্য করবে :)

আপনি কোডটি নেট চালাতে পারেন নেট নেট এখানে:

using System;
using System.Linq;
using System.Collections.Generic;

class Person
{ 
    public int PersonId; 
    public string car  ; 
}

class Result
{ 
   public int PersonId;
   public List<string> Cars; 
}

public class Program
{
    public static void Main()
    {
        List<Person> persons = new List<Person>()
        {
            new Person { PersonId = 1, car = "Ferrari" },
            new Person { PersonId = 1, car = "BMW" },
            new Person { PersonId = 2, car = "Audi"}
        };

        //With Query Syntax

        List<Result> results1 = (
            from p in persons
            group p by p.PersonId into g
            select new Result()
                {
                    PersonId = g.Key, 
                    Cars = g.Select(c => c.car).ToList()
                }
            ).ToList();

        foreach (Result item in results1)
        {
            Console.WriteLine(item.PersonId);
            foreach(string car in item.Cars)
            {
                Console.WriteLine(car);
            }
        }

        Console.WriteLine("-----------");

        //Method Syntax

        List<Result> results2 = persons
            .GroupBy(p => p.PersonId, 
                     (k, c) => new Result()
                             {
                                 PersonId = k,
                                 Cars = c.Select(cs => cs.car).ToList()
                             }
                    ).ToList();

        foreach (Result item in results2)
        {
            Console.WriteLine(item.PersonId);
            foreach(string car in item.Cars)
            {
                Console.WriteLine(car);
            }
        }
    }
}

ফলাফল এখানে:

1
ফেরারী
বগুড়া
2
অডি
-----------
1
ফেরারী
বগুড়া
2
অডি


দয়া করে আপনার কোড খাওয়ার জন্য কী করে তা ব্যাখ্যা করুন। এটি কেবল একটি কোড উত্তর যা প্রায় একটি ভুল উত্তর।
ভি 7

2

এটা চেষ্টা কর :

var results= persons.GroupBy(n => n.PersonId)
            .Select(g => new {
                           PersonId=g.Key,
                           Cars=g.Select(p=>p.car).ToList())}).ToList();

তবে কার্য সম্পাদন অনুসারে নিম্নলিখিত অনুশীলনটি মেমরির ব্যবহারে আরও ভাল এবং আরও অনুকূলিতকরণযোগ্য (যখন আমাদের অ্যারেটিতে লক্ষ লক্ষের মতো আরও বেশি আইটেম রয়েছে):

var carDic=new Dictionary<int,List<string>>();
for(int i=0;i<persons.length;i++)
{
   var person=persons[i];
   if(carDic.ContainsKey(person.PersonId))
   {
        carDic[person.PersonId].Add(person.car);
   }
   else
   {
        carDic[person.PersonId]=new List<string>(){person.car};
   }
}
//returns the list of cars for PersonId 1
var carList=carDic[1];

4
g.Key.PersonId? g.SelectMany?? আপনি পরিষ্কারভাবে এটি চেষ্টা করেন নি।
জার্ট আর্নল্ড

আপনি লিখছেন আমি এতে কিছু কোড কোড সম্পাদনা করেছি এবং এটি পরীক্ষা করি নি। আমার মূল বিষয় ছিল দ্বিতীয় অংশ। তবে যাইহোক আপনার বিবেচনার জন্য ধন্যবাদ। এই কোডটি সম্পাদনা করতে দেরি হয়ে গেছে যখন আমি বুঝতে পারি যে এটি ভুল wrong সুতরাং g.Key g.Key.PersonId প্রতিস্থাপন করে, এবং SelayMany চেয়ে নির্বাচন করুন! তাই অগোছালো দুঃখিত :)))
একাজেমিস

2
@ ਕਾাজেমিস: আমি আসলে তৈরি করার চেষ্টা করছিলাম (ওপির ডোমেনের সমতুল্য শর্তাদি ব্যবহার করতে) SortedDictionary <PersonIdInt, SortedDictionary <CarNameString, CarInfoClass>>। লিনকিউ ব্যবহার করতে পারার সবচেয়ে কাছাকাছি ছিল IEnumerable <IGrouping <PersonIdInt, Dictionary <CarNameString, PersonIdCarNameXrefClass>>>। আমি আপনার forলুপ পদ্ধতিটি ব্যবহার করে শেষ করেছি যা বিটিডব্লিউ 2x দ্রুত ছিল। এছাড়াও, আমি ব্যবহার করব: ক) foreachবনাম forএবং খ) TryGetValueবনাম ContainsKey(উভয়ই ডিআরওয়াই নীতি - কোড এবং রানটাইমের ক্ষেত্রে)।
টম

1

এটি করার একটি বিকল্প উপায় পৃথক PersonIdএবং গ্রুপের সাথে নির্বাচন করে নির্বাচন করা যেতে পারে persons:

var result = 
    from id in persons.Select(x => x.PersonId).Distinct()
    join p2 in persons on id equals p2.PersonId into gr // apply group join here
    select new 
    {
        PersonId = id,
        Cars = gr.Select(x => x.Car).ToList(),
    };

বা অনর্গল এপিআই সিনট্যাক্সের সাথে একই:

var result = persons.Select(x => x.PersonId).Distinct()
    .GroupJoin(persons, id => id, p => p.PersonId, (id, gr) => new
    {
        PersonId = id,
        Cars = gr.Select(x => x.Car).ToList(),
    });

গ্রুপজউইন প্রথম তালিকায় প্রবেশের একটি তালিকা তৈরি করে ( PersonIdআমাদের ক্ষেত্রে তালিকা তৈরি করে), প্রতিটি গ্রুপের সাথে দ্বিতীয় তালিকায় যোগ হওয়া এন্ট্রিগুলির একটি তালিকা রয়েছে (তালিকার তালিকা persons)।


1

নীচের উদাহরণটি গ্রুপবিহীন বস্তুগুলি ফিরতে গ্রুপবি পদ্ধতি ব্যবহার করে PersonID

var results = persons.GroupBy(x => x.PersonID)
              .Select(x => (PersonID: x.Key, Cars: x.Select(p => p.car).ToList())
              ).ToList();

অথবা

 var results = persons.GroupBy(
               person => person.PersonID,
               (key, groupPerson) => (PersonID: key, Cars: groupPerson.Select(x => x.car).ToList()));

অথবা

 var results = from person in persons
               group person by person.PersonID into groupPerson
               select (PersonID: groupPerson.Key, Cars: groupPerson.Select(x => x.car).ToList());

অথবা আপনি ToLookupমূলত ToLookupব্যবহার করতে পারেন। EqualityComparer<TKey>কীগুলি তুলনা করতে এবং গ্রুপ অনুসারে এবং অভিধানে গ্রুপ ব্যবহার করার সময় আপনাকে ম্যানুয়ালি কী করা উচিত তা করতে ডিফল্ট আমি মনে করি এটি উত্তেজিত

 ILookup<int, string> results = persons.ToLookup(
            person => person.PersonID,
            person => person.car);

-1

প্রথমে আপনার কী ক্ষেত্রটি সেট করুন। তারপরে আপনার অন্যান্য ক্ষেত্রগুলি অন্তর্ভুক্ত করুন:

var results = 
    persons
    .GroupBy(n => n.PersonId)
    .Select(r => new Result {PersonID = r.Key, Cars = r.ToList() })
    .ToList()

অ-মন্তব্য করা উত্তর / কোড স্ট্যাকওভারফ্লো কীভাবে কাজ করে তা নয় ...
ভি 7
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.