Помогите с простым запросом Linq
От: Аноним  
Дата: 11.06.10 14:03
Оценка:
Вот код примера, почему-то возвращается пустая запись, не могу понять где ошибка, вроде все логично.

И второй вопрос — может как-то можно проще оформить, особенно вывод writeline

        static void Main(string[] args)
        {

            /// Задача :
            /// Нужно выбрать записи :
            /// 1.  d = 1
            /// 2.  значение b в результирующей выборке должно быть уникальным, 
            /// из множества строк с одинаковым b  нужно оставить одну строку 
            /// у которой максимальное a
            /// т.е. на выходе должны остаться 2 строки
            /// new { a = 2, b = 1, c = 4, d = 1 },
            /// new { a = 6, b = 2, c = 1, d = 1 }

            

            var data = new [] 
            {
                new { a = 1, b = 1, c = 3, d = 1 },
                new { a = 2, b = 1, c = 4, d = 1 },
                new { a = 3, b = 1, c = 5, d = 2 },
                new { a = 4, b = 2, c = 2, d = 1 },
                new { a = 5, b = 2, c = 4, d = 1 },
                new { a = 6, b = 2, c = 1, d = 1 },
            };


           /// Решение :
            /// Запросом  data.Where(max => max.b == d.b).Max(m => m.a) отбираем записи из data
            /// у которых значение max.b равно текущему d.b и находим максимальное m.a для текущего d.b
            /// далее запросом
            /// where (d.d == 1) && (d.a == data.Where(max => max.b == d.b).Max(m => m.a) )
            /// отбираем значения с d =1 и только те у которых d.a = максимальному a в рамках одного b
            var res =
                from d in data
                where (d.d == 1) && (d.a == data.Where(max => max.b == d.b).Max(m => m.a) )
                select new { d.a, d.b, d.c, d.d };


            res.Aggregate((acc, exp) =>
            {
                Console.WriteLine(string.Format("a = {0} , b = {1}, c  = {2}, d = {3}",
                    exp.a, exp.b, exp.c, exp.d)); return exp;
            });
            
            Console.ReadKey();


        }
Re: Помогите с простым запросом Linq
От: Danchik Украина  
Дата: 11.06.10 14:16
Оценка: 4 (1)
Здравствуйте, Аноним, Вы писали:

А>Вот код примера, почему-то возвращается пустая запись, не могу понять где ошибка, вроде все логично.


Для меня так логичней
            var res =
                from item in data
                where (item.d == 1)
                group item by item.b
                into g
                select g.OrderByDescending(i => i.a).First();
Re[2]: Помогите с простым запросом Linq
От: Аноним  
Дата: 11.06.10 14:25
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Здравствуйте, Аноним, Вы писали:


А>>Вот код примера, почему-то возвращается пустая запись, не могу понять где ошибка, вроде все логично.


D>Для меня так логичней

D>
D>            var res =
D>                from item in data
D>                where (item.d == 1)
D>                group item by item.b
D>                into g
D>                select g.OrderByDescending(i => i.a).First();

D>



Возможно, но почему-то выводится 1 запись только, а должно 2 быть ведь у b два уникальных значения.
Re[3]: Помогите с простым запросом Linq
От: Danchik Украина  
Дата: 11.06.10 14:31
Оценка:
Здравствуйте, Аноним, Ві писали:

[Skip]
А>Возможно, но почему-то выводится 1 запись только, а должно 2 быть ведь у b два уникальных значения.

Потому что руки кривые в двух местах были
            foreach (var exp in res)
            {
                Console.WriteLine(string.Format("a = {0} , b = {1}, c  = {2}, d = {3}",
                    exp.a, exp.b, exp.c, exp.d)); 
            }
Re[4]: Помогите с простым запросом Linq
От: Аноним  
Дата: 11.06.10 14:40
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Здравствуйте, Аноним, Ві писали:


D>[Skip]

А>>Возможно, но почему-то выводится 1 запись только, а должно 2 быть ведь у b два уникальных значения.

D>Потому что руки кривые в двух местах были

D>
D>            foreach (var exp in res)
D>            {
D>                Console.WriteLine(string.Format("a = {0} , b = {1}, c  = {2}, d = {3}",
D>                    exp.a, exp.b, exp.c, exp.d)); 
D>            }

D>



Да уж )
Спасибо !

А есть понимание почему мой вариант не работал ? а то я уже себе вывих мозга заработал, хотелось бы понять ошибку.

И еще попутный вопрос — как отлаживать такие запросы, например в процессе отладки узнать что возвращает подзапрос выделенный жирным



            var res =
                from d in data
                where (d.d == 1) && (d.a == data.Where(max => max.b == d.b).Max(m => m.a) )
                select new { d.a, d.b, d.c, d.d };
Re[5]: Помогите с простым запросом Linq
От: Danchik Украина  
Дата: 11.06.10 15:15
Оценка: 4 (1)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Danchik, Вы писали:


[Skip]

А>А есть понимание почему мой вариант не работал ? а то я уже себе вывих мозга заработал, хотелось бы понять ошибку.


            var res =
                from d in data
                where (d.d == 1) &&
                      (d.a == data.Where(max => max.b == d.b /* это куда дел ? :) ===> */&& max.d == 1).Max(m => m.a))
                select new {d.a, d.b, d.c, d.d};


И все таки мой вариант мне как-то больше по душе, особенно когда записей будет побольше.

А>И еще попутный вопрос — как отлаживать такие запросы, например в процессе отладки узнать что возвращает подзапрос выделенный жирным


Черт его знает разбивать на меньшие подзапросы.
Re: Помогите с простым запросом Linq
От: i1yich  
Дата: 12.06.10 15:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вот код примера, почему-то возвращается пустая запись, не могу понять где ошибка, вроде все логично.


А>
А>        static void Main(string[] args)
А>        {

А>            /// Задача :
А>            /// Нужно выбрать записи :
А>            /// 1.  d = 1
А>            /// 2.  значение b в результирующей выборке должно быть уникальным, 
А>            /// из множества строк с одинаковым b  нужно оставить одну строку 
А>            /// у которой максимальное a
А>            /// т.е. на выходе должны остаться 2 строки
А>            /// new { a = 2, b = 1, c = 4, d = 1 },
А>            /// new { a = 6, b = 2, c = 1, d = 1 }

            

А>            var data = new [] 
А>            {
А>                new { a = 1, b = 1, c = 3, d = 1 },
А>                new { a = 2, b = 1, c = 4, d = 1 },
А>                new { a = 3, b = 1, c = 5, d = 2 },
А>                new { a = 4, b = 2, c = 2, d = 1 },
А>                new { a = 5, b = 2, c = 4, d = 1 },
А>                new { a = 6, b = 2, c = 1, d = 1 },
А>            };
А>        }
А>


У тебя получится ужасный по производительности код.
Используй метод расширения
        public static TSource MaxOver<TSource, TMember>(this IEnumerable<TSource> source, Func<TSource, TMember> selector)

который возвращает тот элемент из source, для которого функция selector возвращает максимальное значение. Тогда твой запрос будет выглядеть:

            var res =
                from dg in 
                    (from d in data
                     where d.d == 1
                     group d by d.b)
                select dg.MaxOver(d => d.a);


Единственная здесь трудность в том, что такой метод расширения нужно написать. Могу поделиться своей реализацией.
Re: Помогите с простым запросом Linq
От: Lloyd Россия  
Дата: 12.06.10 15:48
Оценка:
Здравствуйте, Аноним, Вы писали:

А>И второй вопрос — может как-то можно проще оформить,


var q = from l in data
        where l.d == 1
        let g = from m in data
                where m.d == l.d && m.b == l.b && m.a > l.a
                select m
        where !g.Any()
        select l;
Re[6]: Помогите с простым запросом Linq
От: Аноним  
Дата: 12.06.10 18:05
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, Danchik, Вы писали:


D>[Skip]


А>>А есть понимание почему мой вариант не работал ? а то я уже себе вывих мозга заработал, хотелось бы понять ошибку.


D>
D>            var res =
D>                from d in data
D>                where (d.d == 1) &&
D>                      (d.a == data.Where(max => max.b == d.b /* это куда дел ? :) ===> */&& max.d == 1).Max(m => m.a))
D>                select new {d.a, d.b, d.c, d.d};
D>


Спасибо. Посыплю себе все части тела пеплом. )

А>>И еще попутный вопрос — как отлаживать такие запросы, например в процессе отладки узнать что возвращает подзапрос выделенный жирным


D>Черт его знает разбивать на меньшие подзапросы.


Да вот с отладкой что-то не продумано, или мы пока об этом не знаем
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.