Click here to Skip to main content
15,881,027 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
public class Car
    {
        [JsonProperty("name")]
        public string Name{get;set;}
        [JsonProperty("type")]
        public string Type{get;set;}
    }


public class CarOwner
    {
        [JsonProperty("name")]
        public string Name{get;set;}
        [JsonProperty("gender")]
        public string Gender{get;set;}
        [JsonProperty("age")]
        public int Age{get;set;}
        [JsonProperty("cars")]
        public List<Car> Cars{get;set;}
    }


public class Result
    {
        public string Gender { get; set; }
        public List<string> Name { get; set; }
    }


I need to group by gender and display all names of cars under it in alphabetically sorted order. e..g

Male:
Ambassador (sorted albhabetically)
Lamborghini
Maruti

Female :
Bugatti (sorted alphabetically)
Maruti
Scooty

What I have tried:

var z = m.Where(b => b.Cars != null).Select(k => new Result{Gender = k.Gender, Name = k.Cars.Where(t => t.Type.Contains("Heavy")).Select(h => h.Name).ToList()});
		var o= z.OrderBy(l=>l.Name).GroupBy(p=>p.Gender);
Posted
Updated 16-May-18 7:03am
v3
Comments
sam_roy 13-May-18 16:15pm    
First Part is solved I am able to retrieve as below:

var z = m.Where(b => b.Cars!= null).Select( k =>new Result
{
Gender=k.Gender,
Name=k.Cars.Where(t => t.Type.Contains("Heavy")).Select(h=>h.Name).ToList()
});

Actually one more thing is needed to finally display all the names of the cars under headers segregated on "Gender" on sorted order. Can it be possible in that single query?
Christian Graus 13-May-18 19:12pm    
Your question makes no sense. You want to group by Gender?
sam_roy 14-May-18 1:17am    
Yes Christian I want to group by Gender and order by Names of the car. The final touch is still remaining.
#realJSOP 16-May-18 10:02am    
DUDE! I didn't know you were still active on CP. :)
sam_roy 14-May-18 1:17am    
Yes Christian I want to group by Gender and order by Names of the car. The final touch is still remaining.

var results = owners.Where(b => b.Cars != null)
     .GroupBy(o => o.Gender, o => o.Cars, (key, g) =>
  new Result { Gender = key, Name = g.SelectMany(cars => cars)
      .Select(car => car.Name).Distinct().OrderBy(k => k).ToList() });

I forgot the order by for car names.

Here I added the Where clause that will remove owners with null cars.
 
Share this answer
 
v4
Comments
#realJSOP 16-May-18 13:25pm    
Have you tried running this? When I stop in the debugger after executing this line of code, I get an error in the results collection - Object not set to the instance of an object. If you need the sample data, I did this to test my code:

List<CarOwner> owners = new List<CarOwner>()
{
    new CarOwner(){Name="Hari", Gender="Male",Age=23,      Cars= new List<Car>(){new Car(){Name="Ambassador", Type="Heavy"},new Car(){Name="Maruti", Type="Light"}}},
    new CarOwner(){Name="Ruchira", Gender="Female",Age=18, Cars= new List<Car>(){new Car(){Name="Sumo", Type="Heavy"}}},
    new CarOwner(){Name="Shyam", Gender="Male",Age=45,       Cars= null},
    new CarOwner(){Name="Rakesh", Gender="Male",Age=40,      Cars= new List<Car>(){new Car(){Name="Renault", Type="Heavy"},new Car(){Name="Pageiro", Type="Heavy"}}},
    new CarOwner(){Name="Sarmistha", Gender="Female",Age=40, Cars= new List<Car>(){new Car(){Name="Innova", Type="Heavy"},new Car(){Name="Maruti", Type="Light"},new Car(){Name="Eon",Type="Light"},new Car(){Name="Jeep",Type=""}}},
    new CarOwner(){Name="Aliah", Gender="Female",Age=64,     Cars= new List<Car>(){new Car(){Name="Bolero", Type="Heavy"},new Car(){Name="Hyundai", Type="Light"}}},
};
Clifford Nelson 16-May-18 13:28pm    
Yes, Copied from working console application. It has been fixed to deal with null Cars property.
#realJSOP 16-May-18 13:33pm    
What version of .Net? I'm using 4.5.
#realJSOP 16-May-18 13:37pm    
Even after your change, I still get that error when I try to inspect the results collection.
sam_roy 16-May-18 15:45pm    
Suppose The class is generated from a JSON by JSON Converter and the Cars Property can be Null or the Gender property is null. We cannot assume it. Is there any defensive way of writing Lambda for the Group key and the main select items?
The structure of your objects (Car and CarOwner) prevents you from getting what you want (without additional coding). First, you shouldn't try to do everything in one line of code. IT's not that it's not possible, it's that it's bad practice because it is HIGHLY unmaintainable.

Add this class:
C#
public class GenderCar
{
    public string Gender { get; set; }
    public string CarName { get; set; }
}

Modify this class (add the new method)
C#
public class Result
{
    public string Gender { get; set; }
    public List<string> Name { get; set; }
    public List<GenderCar> GetCars()
    {
        List<GenderCar> gc = new List<GenderCar>();
        foreach(string name in Name)
        {
            gc.Add(new GenderCar(){Gender = this.Gender, CarName = name});
        }
        return gc;
    }
}


And your usage will look like this (owners is defined as List<CarOwnerCar>, and is populated when you deserialize your JSON data):
C#
// get all of the car owners with at least one "heavy" car
List<Result> cars = owners.Where(b => b.Cars != null).Select(k => 
    new Result{Gender = k.Gender, Name = k.Cars.Where(t => t.Type.Contains("Heavy")).Select(h => h.Name).ToList()}).ToList();

// now get all the cars for all of the car owners, as well as the gender of the owner
List<GenderCar> gendercars = new List<GenderCar>();
foreach (Result res in cars)
{
    gendercars.AddRange(res.GetCars());
}

// sort the gender cars list by gender (descending, because your requirements 
// indicated that male owners be listed first), and then by car name
gendercars = gendercars.OrderByDescending(x=>x.Gender).ThenBy(x=>x.CarName).ToList();

// display the results
string gender = string.Empty;
foreach (GenderCar car in gendercars)
{
    // if the gender changes, perform some special output indicating the 
    // current gender being processed
    if (gender != car.Gender)
    {
        gender  = car.Gender;
        Console.WriteLine(gender+":");
    }

    // output the car name
    Console.WriteLine("    "+car.CarName);
}

Console.ReadKey();


Final note - your variable naming could use some work.

EDIT ===========================

Your insistence on using overly complex Linq statements is preventing you from moving on in the code. In real world development, your manager will become quite annoyed with your efforts to falsely optimize the code. Make it simple, which makes it maintainable. That's the ultimate key to success as a developer.
 
Share this answer
 
v8
Comments
Clifford Nelson 16-May-18 13:04pm    
Did not use linq like he wanted.
#realJSOP 16-May-18 13:16pm    
Just because you can doesn't mean you should. Besides, there's all kinds of Linq in my answer. :)

BTW, My answer provides the output which he was seeking, so I should at least get a 3. >:\

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900