sam_roy Ответов: 2

Лямбда-запрос помогает с группировкой и упорядочиванием.


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; }
    }


Мне нужно сгруппировать по полу и отобразить все названия автомобилей под ним в алфавитном порядке. например

Мужчина:
Посол (сортируется альбхабетически)
Lamborghini
Компания

Женский :
Bugatti (сортировка по алфавиту)
Компания
Скутер

Что я уже пробовал:

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);

sam_roy

Первая часть решена я могу получить как показано ниже:

var z = m.где(b => b.Cars!= null).Выберите( k =>новый результат
{
Пол=k.пол,
Имя=k.автомобили.Где(t => t.Тип.Содержит("Тяжелый")).Выберите(h=>h.Name).Список()
});

На самом деле нужно еще кое-что, чтобы окончательно отобразить все названия автомобилей под заголовками, разделенными по "полу" в отсортированном порядке. Может ли это быть возможно в этом единственном запросе?

Christian Graus

Твой вопрос не имеет смысла. Вы хотите сгруппироваться по полу?

sam_roy

Да, я хочу сгруппировать по полу и заказать по названиям машины. Последний штрих все еще остается.

#realJSOP

Чувак! Я не знал, что ты все еще работаешь на КП. :)

sam_roy

Да, я хочу сгруппировать по полу и заказать по названиям машины. Последний штрих все еще остается.

sam_roy

Хотите показать как :

Мужчина: (Ключ Гендерной Группы)
Астор (сортированный порядок альбхабетически)
Бугати (сортировка по порядку альбхабетически)

Женщина: (ключ гендерной группы)
Maruti (сортированный порядок albhabetically)
Яд (сортировка по порядку альбхабетически)

sam_roy

Требуемый формат JSON:

[{"name":"Hari","gender":"Male","age":23,"cars":[{"name":"Ambassador","type":"Heavy"},{"name":"Maruti","type":"Light"}]},{"name":"Ruchira","gender":"Female","age":18,"cars":[{"name":"Sumo","type":"Heavy"}]},{"name":"Shyam","gender":"Male","age":45,”cars”:null},{"name":"Rakesh","gender":"Male","age":40,”cars”:[{"name":"Renault","type":”Heavy”},{"name":"Pageiro","type":”Heavy”},{"name":"Eon","type":”Light”},{"name":"Jeep","type":”Heavy”}]},{"name":"Sarmistha","gender":"Female","age":40,”cars”:[{"name":"Innova","type":”Heavy”}]},{"name":"Aliah","gender":"Female","age":64,”cars”:[{"name":"Bolero","type":”Heavy”},{"name":"Hyundai","type":”Light”}]}]

Member 12810461

можете ли вы поделиться кодом? чтобы я мог вставить его в VS и проверить ваш сценарий для отладки?

2 Ответов

Рейтинг:
17

Clifford Nelson

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() });

Я забыл заказать по названиям машин.

Здесь я добавил предложение Where, которое удалит владельцев с нулевыми автомобилями.


#realJSOP

Вы пробовали запустить это? Когда я останавливаюсь в отладчике после выполнения этой строки кода, я получаю ошибку в коллекции результатов - Object not set to the instance of an object Если вам нужны примеры данных, я сделал это, чтобы проверить свой код:

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

Да, скопировано из рабочего консольного приложения. Он был исправлен для работы с нулевым свойством автомобилей.

#realJSOP

Какая версия .Net? Я использую 4.5.

#realJSOP

Даже после вашего изменения я все еще получаю эту ошибку, когда пытаюсь проверить results коллекция.

sam_roy

Предположим, что класс формируется из JSON с помощью JSON конвертер и имущества вагонов может быть нулем, или гендерное свойство имеет значение null. Мы не можем этого допустить. Существует ли какой-либо защитный способ написания лямбды для ключа группы и основных элементов выбора?

sam_roy

Клиффорд Нильсон: Предположим, мы не можем предсказать Null, поскольку он десериализуется с помощью JSONConverter. Существует ли какой-либо способ защитного кодирования для обработки null в групповом ключе(пол) и списке (автомобили)? так что selectMany не подведет.

Рейтинг:
0

#realJSOP

Структура ваших объектов (автомобиль и владелец автомобиля) не позволяет вам получить то, что вы хотите (без дополнительного кодирования). Во - первых, вы не должны пытаться сделать все в одной строке кода. Дело не в том, что это невозможно, а в том, что это плохая практика, потому что она в высшей степени недостижима.

Добавьте этот класс:

public class GenderCar
{
    public string Gender { get; set; }
    public string CarName { get; set; }
}

Измените этот класс (добавьте новый метод)
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;
    }
}


И ваше использование будет выглядеть так (owners определяется как List<CarOwnerCar>, и заполняется при десериализации данных JSON):
// 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();


Последнее замечание - ваше именование переменных может потребовать некоторой работы.

РЕДАКТИРОВАТЬ ===========================

Ваша настойчивость в использовании слишком сложных операторов Linq мешает вам двигаться дальше в коде. В реальной разработке ваш менеджер будет очень раздражен вашими попытками ложно оптимизировать код. Сделайте его простым, что делает его ремонтопригодным. Это главный ключ к успеху в качестве разработчика.


Clifford Nelson

Не использовал linq, как он хотел.

#realJSOP

То, что ты можешь, еще не значит, что ты должен. Кроме того, в моем ответе есть все виды Linq. :)

Кстати, мой ответ дает результат, который он искал, так что я должен, по крайней мере, получить 3. >:\