Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.87/15: Рейтинг темы: голосов - 15, средняя оценка - 4.87
 Аватар для me_hungry
7 / 7 / 2
Регистрация: 25.04.2014
Сообщений: 23
.NET 3.x

Группировка используя LINQ + сумма стрингов

12.08.2016, 17:37. Показов 2979. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет!!
Хочу реализовать отчетик* в среде 3D моделирования.

Есть элемент например с именем 'V1', описанием 'Задвижка' и материалом 'Сталь 20'.
Пример этих полей в виде строк а-ля CSV:
;Клапан;Сталь 20;1;V1
;Клапан;Сталь 20;1;V2
;Задвижка;Сталь 20;1;V3

Мне нужно получить:
;Клапан;Сталь 20;2;V1,V2
;Задвижка;Сталь 20;1;V3


Использую код, но не внося имя в класс Element:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    class Program
    {
        static void Main(string[] args)
        {
            List<Element> ElementList = new List<Element>();
            ElementList = new List<Element>
                {
            new Element() {desc = "Фильтр LTR ",material="Сталь 20",quan=1 },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1 },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1 },
 
            };
            var query = ElementList
             .OrderBy(d => d.desc)
             .GroupBy(g => new { g.desc, g.material })
             .Select(group => new
             {
                 desc = group.Key.desc,
                 mat = group.Key.material,
                 Quantity = group.Sum(Q => Q.quan),
             });
            foreach (var item in query)
            {
                Console.WriteLine("{0};{1};{2}",
                          item.desc,
                          item.mat,
                          item.Quantity);
            }
            Console.ReadLine();
        }
    }
    class Element
    {
        public string desc { get; set; }
        public string material { get; set; }
        public int quan { get; set; }
    }
Все группирует и сортирует, количество пишет одинаковых элементов, если без имени.
;Клапан;Сталь 20;2
;Задвижка;Сталь 20;1

Помогите собирать имена по аналогу с количество?!
Спасибо
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
12.08.2016, 17:37
Ответы с готовыми решениями:

Linq Группировка данных
Есть коллекция: id name atherId sum ---------------------- 1, &quot;aaa&quot;, 1, 10 1, &quot;aaa&quot;, 2, 11 1, ...

LINQ: вложенная группировка
Добрый день! Есть список детей первых классов. У каждого ребенка известен пол, возраст и в каком классе он учится. List&lt;Kid&gt;...

LINQ и группировка по нескольким полям
Здравствуйте, Есть таблица с полями 5-ю полями &quot;p1&quot;, &quot;p2&quot;, &quot;p3&quot;, &quot;p4&quot;, &quot;а&quot;. Нужно найти суммы поля &quot;а&quot; раздельно по всем...

13
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
12.08.2016, 17:50
Цитата Сообщение от me_hungry Посмотреть сообщение
Помогите собирать имена по аналогу с количество?!
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
using System;
using System.Collections.Generic;
using System.Linq;
 
namespace ConsoleApplication212
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Element> ElementList = new List<Element>();
            ElementList = new List<Element>
                {
            new Element() {desc = "Фильтр LTR ",material="Сталь 20",quan=1, Name = "V1" },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1, Name = "V2" },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1, Name = "V3" },
 
            };
            var query = ElementList
             .OrderBy(d => d.desc)
             .GroupBy(g => new { g.desc, g.material })
             .Select(group => new
             {
                 desc = group.Key.desc,
                 mat = group.Key.material,
                 Quantity = group.Sum(Q => Q.quan),
                 Name = group.Aggregate("", (a, b)=>a + b.Name + ",")
             });
            foreach (var item in query)
            {
                Console.WriteLine("{0};{1};{2};{3}",
                          item.desc,
                          item.mat,
                          item.Quantity,
                          item.Name.TrimEnd(','));
            }
            Console.ReadLine();
        }
    }
 
    class Element
    {
        public string desc { get; set; }
        public string material { get; set; }
        public int quan { get; set; }
        public string Name { get; set; }
    }
}
А вообще LINQ предназначен для упрощения манипуляций с данными. Если ваш LINQ становится слишком сложным - может имеет смысл использовать старый добрый foreach?
1
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
12.08.2016, 17:59
Storm23, string.Join смотрит на group.Aggregate c недоумением.
Да и запрос не скажу что капец. Решарпер помню мне такое советовал заворачивать, что потом смотреть на это было невозможно
0
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
12.08.2016, 18:15
А почему не вывести так?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
            List<Element> ElementList = new List<Element>();
            ElementList = new List<Element>
                {
            new Element() {desc = "Фильтр LTR ",material="Сталь 20",quan=1 },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1 },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1 },
            new Element() {desc = "Задвижка ",material="Сталь 21",quan=1 },
            };
            var result = ElementList
                .OrderBy(e=>e.desc)
                .GroupBy(e => new {e.desc, e.material }).Select(e =>
            $"{e.First().desc}; {e.First().material}; {e.Count()}");
            Console.WriteLine(string.Join("\n", result));
            Console.ReadKey(false);
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
12.08.2016, 18:21
Цитата Сообщение от Psilon Посмотреть сообщение
Storm23, string.Join смотрит на group.Aggregate c недоумением.
It is true LINQ way
0
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
12.08.2016, 18:41
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace linq03
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Element> ElementList = new List<Element>();
            ElementList = new List<Element>
                {
            new Element() {desc = "Фильтр LTR ",material="Сталь 20",quan=1, Name = "V1" },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1, Name = "V2" },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1, Name = "V3" },
            new Element() {desc = "Задвижка ",material="Сталь 21",quan=1, Name = "V4" },
            };
            var result = ElementList
                .OrderBy(e=>e.desc)
                .GroupBy(e =>
                new {e.desc, e.material }).Select((s, i) =>
            $"{s.First().desc}; {s.First().material}; {s.Count()}; {string.Join(", ", s.Select(e=>e.Name))}");
            Console.WriteLine(string.Join("\n", result));
            Console.ReadKey(false);
        }
    }
    class Element
    {
        public string desc { get; set; }
        public string material { get; set; }
        public int quan { get; set; }
        public string Name { get; set; }
    }
}
0
 Аватар для me_hungry
7 / 7 / 2
Регистрация: 25.04.2014
Сообщений: 23
12.08.2016, 18:42  [ТС]
@Storm23,@Psilon, @EveKS
Коллеги большое спасибо, за быстрый ответ!!
А вообще LINQ предназначен для упрощения манипуляций с данными. Если ваш LINQ становится слишком сложным - может имеет смысл использовать старый добрый foreach?
Я пытаюсь сделать максимально читабельным код, просто в конечном счете выйдет такая борода:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
var querylValvAssemblies = lValvAssemblies
                     .GroupBy(g => new
                     {
                         g.SKHValvRef,
                         g.Rati,
                         g.PGroupAndCategory,
                         g.PDesignTemp,
                         g.FluidDescription1,
                         g.fluidstate,
                         g.ABOR,
                         g.WallThickness,
                         g.PDesignPres,
                         g.CorrosionSpid,
                         g.FluidDescription2,
                         g.iType,
                         g.DTXR,
                         g.MTXY,
                         g.MTXX,
                         g.sQuan,
                         g.Type,
                         g.Quan
                     })
                     .Select(group => new
                     {
                         SKHValvRef = group.Key.SKHValvRef,
                         Rati = group.Key.Rati,
                         PGroupAndCategory = group.Key.PGroupAndCategory,
                         PDesignTemp = group.Key.PDesignTemp,
                         FluidDescription1 = group.Key.FluidDescription1,
                         fluidstate = group.Key.fluidstate,
                         ABOR = group.Key.ABOR,
                         WallThickness = group.Key.WallThickness,
                         PDesignPres = group.Key.PDesignPres,
                         CorrosionSpid = group.Key.CorrosionSpid,
                         FluidDescription2 = group.Key.FluidDescription2,
                         IType = group.Key.iType,
                         DTXR = group.Key.DTXR,
                         MTXY = group.Key.MTXY,
                         MTXX = group.Key.MTXX,
                         Type = group.Key.Type,
                         Quantity = group.Sum(C => C.Quan),
                     })
                     .OrderBy(order => order.Rati)
                     .ThenBy(order => order.PGroupAndCategory)
                     .ThenBy(order => order.PDesignTemp)
                     .ThenBy(order => order.FluidDescription1)
                     .ThenBy(order => order.fluidstate)
                     .ThenBy(order => order.WallThickness)
                     .ThenBy(order => order.PDesignPres)
                     .ThenBy(order => order.CorrosionSpid)
                     .ThenBy(order => order.FluidDescription2)
                     .ThenBy(order => order.SKHValvRef)
                     .ThenBy(order => order.IType)
                     .ThenBy(order => order.ABOR);
@EveKS, не компилится Ваш код
0
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
12.08.2016, 18:57
Лучший ответ Сообщение было отмечено me_hungry как решение

Решение

Всё понял почему не подходящий ответ, т.к
C#
1
Quantity = group.Sum(Q => Q.quan)
.
А это будет повтор выше написанного, если создавать список...
C#
1
$"{s.First().desc}; {s.First().material}; {s.Count()}; {string.Join(", ", s.Select(e=>e.Name))}");
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
            List<Element> ElementList = new List<Element>();
            ElementList = new List<Element>
                {
            new Element() {desc = "Фильтр LTR ",material="Сталь 20",quan=1, Name = "V1" },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1, Name = "V2" },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1, Name = "V3" },
            new Element() {desc = "Задвижка ",material="Сталь 21",quan=1, Name = "V4" },
            };
            var result = ElementList
                .OrderBy(e => e.desc)
                .GroupBy(e =>
                new { e.desc, e.material }).Select(s =>
                new
                {
                    desc = s.First().desc,
                    material = s.First().material,
                    quan = s.Sum(e=>e.quan),
                    name = string.Join(", ", s.Select(e => e.Name))
                })
            ;
            Console.WriteLine(string.Join("\n", result));
            Console.ReadKey(false);
Добавлено через 1 минуту
me_hungry, может из-за $"{var}" не компилируется?
1
 Аватар для me_hungry
7 / 7 / 2
Регистрация: 25.04.2014
Сообщений: 23
12.08.2016, 19:09  [ТС]
@EveKS
Оо-о теперь отлично!!!
Если изменить строку, то будет компиллится и для .net 3.5:
name = String.Join(",", s.Select(e => e.Name).ToArray())
1
Заблокирован
12.08.2016, 19:37
Господа, вы слишком много курите. Хватит писать быдло код на пол листа, для детских задач. Бросаем курить, гавнокодить и рисовать цифры.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
string[] init = {
                "; Клапан; Сталь 20; 1; V1",
                "; Клапан; Сталь 20; 1; V2",
                "; Задвижка; Сталь 20; 1; V3"
            };
 
            var result = from _ in init
                         let elem = _.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries)
                         group elem by elem[0] + elem[1] into g
                         select String.Concat(";", g.First()[0].TrimStart(), ";", g.First()[1].TrimStart(), ";", g.Sum(x => int.Parse(x[2])), ";",
                         String.Join(",", g.Select(x => x[3].Trim())));
 
 
            foreach (var elem in result) Console.WriteLine(elem);
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
12.08.2016, 19:39
Dsasdf, взял, придумал свою задачу, решил её достаточно кривым способом, и говорит, что вокруг все дураки Ай малаца.
0
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
12.08.2016, 20:43
Если вариант Dsasdf, реализовать со списком, то возможно так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
            List<Element> ElementList = new List<Element>();
            ElementList = new List<Element>
                {
            new Element() {desc = "Фильтр LTR ",material="Сталь 20",quan=1, Name = "V1" },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1, Name = "V2" },
            new Element() {desc = "Задвижка ",material="Сталь 20",quan=1, Name = "V3" },
            new Element() {desc = "Задвижка ",material="Сталь 21",quan=1, Name = "V4" },
            };
            var result = from e in ElementList
                         orderby e.desc
                         group e by e.desc + e.material into g
                         select new
                         {
                             desc = g.First().desc,
                             material = g.First().material,
                             quin = g.Sum(e => e.quan),
                             name = string.Join(",", g.Select(x => x.Name))
                         };
                         
            Console.WriteLine(string.Join("\n", result));
            Console.ReadKey(false);
Цитата Сообщение от me_hungry Посмотреть сообщение
Есть элемент например с именем 'V1', описанием 'Задвижка' и материалом 'Сталь 20'.
Пример этих полей в виде строк а-ля CSV:
Поидее, вводные данные - строка, а не список. На выходе да, не совсем понятно что надо, список данных или список строк...
0
 Аватар для me_hungry
7 / 7 / 2
Регистрация: 25.04.2014
Сообщений: 23
12.08.2016, 21:14  [ТС]
Если интересно полностью алгоритм то, есть база данных, из которой я дергаю атрибуты (иногда родительские или вычисляемые), переходя по всем элементам (Задвижка \Фильтр и т.п.).

Заполняю пользовательский объект - Element свойствами desc, material
>Сортирую +Группирую (Лист объектов Element)>Заполняю DataTable -ом, через OpenXML таблицу ворда..Вот
Так что метод EveKS, с помощью Join вполне подойдет - читабельный + немного строк
0
 Аватар для EveKS
601 / 485 / 185
Регистрация: 19.04.2016
Сообщений: 1,885
12.08.2016, 21:23
me_hungry, мой вариант, в итоге - не чем не отличается от Storm23, правда там Agregate.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.08.2016, 21:23
Помогаю со студенческими работами здесь

LInQ и группировка (Формирование grid в Devexpress XAF)
Привет всем. Такое дело.. Есть класс &quot;Работа&quot; объекты которого имеют поля: Исполнитель, ОбъемРаботПлан, МаксЗагрузка и др.... ...

Linq Группировка
Как сделать в linq группировку? var groupQuery = from p in db.Distributions group p by p.Name into groupName ...

Группировка LINQ
Приветствую всех. Я делаю группировку с помощью LINQ вот так var myQuery = from z in allinfo group z by...

Группировка в Linq
Почему-то неправильно работает запрос с группировкой (вместо отдельных чисел выводит кучу массивов): static void GroupingReq()...

Объединение и группировка Linq
Здравствуйте, есть задача по Linq не могу никак решить, помогите. LinqBegin50°. Даны строковые последовательности A и B; все строки в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка SDL3 из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru