locked
Split List<T> based on key? RRS feed

  • Question

  • Hi, 

    I have a list of people in which one of the properties is the department code.  I would like to split this into as many lists as there are there are unique departments.  I've tried lots of lambdas(?) but seem to be missing something.  Anyone care to point out the obvious? 

    At the end I should have three List<Person> 

    • List of IT staff (3)
    • List of BI staff (2)
    • List of support staff (2)

    Thanks 

    void Main()
    {
    	List<Person> persons = GetPersons();
    	
    	// Get distinct department codes 
    	List<String> departments = persons.Select (p => p.Dept ).Distinct().ToList();
    	
    	// Create a List<Person> per deparments list. 
    	List<Person> deptList=null;
    	foreach (String dept in departments)
    	{
    		deptList = new List<Person>();
    		deptList.Add(persons.Find(x => x.Type == dept));
    
    		
    		
    //		Console.WriteLine (persons.Find(x => x.Type == dept));
    		
    		
    	}
    	deptList.Dump();
    
    }
    
    
    List<Person> GetPersons()
    {
    	List<Person> persons = new List<Person>();
    	 
    	persons.Add(new Person {Dept="IT", First="Fred", Last="Bloggs"});
    	persons.Add(new Person {Dept="IT", First="Stan", Last="Smith"});
    	persons.Add(new Person {Dept="IT", First="Peter", Last="Griffin"});	 
    	persons.Add(new Person {Dept="BI", First="Helen", Last="Back"});
    	persons.Add(new Person {Dept="BI", First="Mickey", Last="Mouse"});	 
    	persons.Add(new Person {Dept="Support", First="John", Last="Doe"});
    	persons.Add(new Person {Dept="Support", First="Marty", Last="McFly"});	 
    	return persons;
    }
    
    class Person 
    {
    	public string Dept { get; set; }
    	public string First { get; set; }
    	public string Last { get; set; }
    }
    

    Thursday, October 29, 2015 7:45 PM

Answers

  • Here your search result is based on departments. You need create dynamic List to store List of persons.

    If you want to create separate list for each department you can use the Dictionary or Array. Below I used  the dictionary.

    List<Person> persons = GetPersons();
    
                // Get distinct department codes 
                List<String> departments = persons.Select(p => p.Dept).Distinct().ToList();
    
                // Create a List<Person> per deparments list. 
                List<Person> deptList = null;
    
                //Store Dept List
                Dictionary<string, List<Person>> dcAllData = new Dictionary<string,List<Person>>();
                
                foreach (String dept in departments)
                {
                    deptList = persons.FindAll(e => (e.Dept == dept));
                    //Store dept list by department name
                    dcAllData.Add(dept, deptList);
    
                }


    • Edited by Jigneshk Thursday, October 29, 2015 8:12 PM
    • Proposed as answer by Jigneshk Thursday, October 29, 2015 8:12 PM
    • Marked as answer by The real Slartibartfast Thursday, October 29, 2015 10:14 PM
    Thursday, October 29, 2015 8:11 PM
  • Just

    List<Person> persons = GetPersons();
    
    var personsByDepartment = persons.GroupBy(p => p.Dept).ToDictionary( g => g.Key, g => g.ToList());
                
    David


    David http://blogs.msdn.com/b/dbrowne/



    Thursday, October 29, 2015 8:35 PM
  • For anyone searching in future the main method looks like this and works just fine. 

    void Main()
    {
    	List<Person> persons = GetPersons();
    	var personsByDepartment = persons.GroupBy(p => p.Dept).ToDictionary( g => g.Key, g => g.ToList());
    		
    	foreach (var element in personsByDepartment)
    	{
    		Console.WriteLine (string.Format(@"Found department - {0}", element.Key));
    		foreach (Person p in element.Value)
    		{
    			Console.WriteLine (string.Format(@"{0} {1} ", p.First, p.Last));			
    		}
    		Console.WriteLine ();
    		Console.WriteLine ();
    	}
    }

    • Proposed as answer by SimorC Thursday, October 29, 2015 10:16 PM
    • Marked as answer by The real Slartibartfast Thursday, October 29, 2015 10:22 PM
    Thursday, October 29, 2015 10:14 PM

All replies

  • Here your search result is based on departments. You need create dynamic List to store List of persons.

    If you want to create separate list for each department you can use the Dictionary or Array. Below I used  the dictionary.

    List<Person> persons = GetPersons();
    
                // Get distinct department codes 
                List<String> departments = persons.Select(p => p.Dept).Distinct().ToList();
    
                // Create a List<Person> per deparments list. 
                List<Person> deptList = null;
    
                //Store Dept List
                Dictionary<string, List<Person>> dcAllData = new Dictionary<string,List<Person>>();
                
                foreach (String dept in departments)
                {
                    deptList = persons.FindAll(e => (e.Dept == dept));
                    //Store dept list by department name
                    dcAllData.Add(dept, deptList);
    
                }


    • Edited by Jigneshk Thursday, October 29, 2015 8:12 PM
    • Proposed as answer by Jigneshk Thursday, October 29, 2015 8:12 PM
    • Marked as answer by The real Slartibartfast Thursday, October 29, 2015 10:14 PM
    Thursday, October 29, 2015 8:11 PM
  • Here your search result is based on departments. You need create dynamic List to store List of persons.

    If you want to create separate list for each department you can use the Dictionary or Array. Below I used  the dictionary.

    List<Person> persons = GetPersons();
    
                // Get distinct department codes 
                List<String> departments = persons.Select(p => p.Dept).Distinct().ToList();
    
                // Create a List<Person> per deparments list. 
                List<Person> deptList = null;
    
                //Store Dept List
                Dictionary<string, List<Person>> dcAllData = new Dictionary<string,List<Person>>();
                
                foreach (String dept in departments)
                {
                    deptList = persons.FindAll(e => (e.Dept == dept));
                    //Store dept list by department name
                    dcAllData.Add(dept, deptList);
    
                }

    Thanks, I would not have thought to populate the second element in the dictionary with a complex type, in fact I didn't know that was possible.  

    How would I extract from the List<string, List<Person>> to an ordinary list?  Your code has stored them as below, but I need them separate, i.e. a list for IT, BI etc. 


    Thursday, October 29, 2015 8:29 PM
  • Just

    List<Person> persons = GetPersons();
    
    var personsByDepartment = persons.GroupBy(p => p.Dept).ToDictionary( g => g.Key, g => g.ToList());
                
    David


    David http://blogs.msdn.com/b/dbrowne/



    Thursday, October 29, 2015 8:35 PM
  • If you need in separate list then you have to declare separate variables.

    I believe you want three list and name of list like this.

    This list have all BI persons.
    List<Person> lstBI;

    This list have all IT persons
    List<Person> lstIT;

    If you want that way you have to declare separate variables. That's the only way.

    Does this answer your question?

    Thursday, October 29, 2015 8:50 PM
  • The number of departments can change so I could not hard code List<T>.  However, I don't need separate lists as long as I can iterate thru them.

    Thanks 

     
    Thursday, October 29, 2015 10:11 PM
  • Just

    List<Person> persons = GetPersons();
    
    var personsByDepartment = persons.GroupBy(p => p.Dept).ToDictionary( g => g.Key, g => g.ToList());
                
    David


    David http://blogs.msdn.com/b/dbrowne/



    Yes thanks, that works.  I also moved the GetPersons() call into the second (var) line but it is not that readable, to my eyes anyway. 

    Thursday, October 29, 2015 10:13 PM
  • For anyone searching in future the main method looks like this and works just fine. 

    void Main()
    {
    	List<Person> persons = GetPersons();
    	var personsByDepartment = persons.GroupBy(p => p.Dept).ToDictionary( g => g.Key, g => g.ToList());
    		
    	foreach (var element in personsByDepartment)
    	{
    		Console.WriteLine (string.Format(@"Found department - {0}", element.Key));
    		foreach (Person p in element.Value)
    		{
    			Console.WriteLine (string.Format(@"{0} {1} ", p.First, p.Last));			
    		}
    		Console.WriteLine ();
    		Console.WriteLine ();
    	}
    }

    • Proposed as answer by SimorC Thursday, October 29, 2015 10:16 PM
    • Marked as answer by The real Slartibartfast Thursday, October 29, 2015 10:22 PM
    Thursday, October 29, 2015 10:14 PM