Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.97/29: Рейтинг темы: голосов - 29, средняя оценка - 4.97
3 / 3 / 2
Регистрация: 30.07.2017
Сообщений: 223

Конструктор фильтра

03.04.2018, 12:30. Показов 6425. Ответов 37
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день!
Хочу сделать что-то вроде универсального метода - конструктора фильтра.
В качестве входных параметров предполагается:
1. List<string> PropNames - коллекция имен свойств. Есть свойства, которые присущи нескольким классам. Сами свойства есть экземпляры классов-справочников, которые наследуются от базового класса
C#
1
2
3
4
5
    public class Entity
    {
        public virtual int ID {get; set;}
        public virtual string Description { get; set; }
    }
2. List <List<int>> Values - коллекция допустимых ID для фильтрации коллекции некоего класса (не класс-справочника) по его свойствам.

3. List<SomeEntity> InList - коллекция, предполагаемая к фильтрованию.

Выходные параметры:
1. List<SomeEntity> OutList - отфильтрованная коллекция.

Не знаю с какой стороны подступиться к решению. Готов выслушать любые предложения/идеи.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.04.2018, 12:30
Ответы с готовыми решениями:

Определить конструктор без параметров, конструктор с одним параметром, конструктор с двумя параметрами, деструктор
Создать класс «матрица». Данный класс должен содержать элементы типа int, определяющие число строк, столбцов и состояние ошибки. Определить...

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

Какой метод синтеза фильтра обеспечивает наименьшее число параметров фильтра при заданных ограничениях АЧХ?
Доброго времени суток! Подскажите пожалуйста,какой метод синтеза фильтра обеспечивает наименьшее кол-во параметров фильтра при заданных...

37
3 / 3 / 2
Регистрация: 30.07.2017
Сообщений: 223
06.04.2018, 14:25  [ТС]
Студворк — интернет-сервис помощи студентам
Storm23, спасибо! Мне казалось, что я уже два раза объяснил логику фильтра . Может быть плохо
В общем, последний код выглядит и работает именно так как хочется. Остался маленький штрих - изменить логику фильтра с OR на AND. Т.е. выбирать из коллекции SomeMainClass только те сущности, все Id свойств которых входят в свои допустимые коллекции.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
06.04.2018, 17:06
Лучший ответ Сообщение было отмечено wrq2017 как решение

Решение

Цитата Сообщение от wrq2017 Посмотреть сообщение
я уже два раза объяснил логику фильтра
Цитата Сообщение от wrq2017 Посмотреть сообщение
изменить логику фильтра с OR на AND
Взаимоисключающие параграфы. Не?
На самом деле, даже сейчас есть неоднозначность - непонятно нужно отбирать по AND только среди тех свойств которые присутствуют в объекте, или же все свойства должны обязательно присутствовать в объекте.
Если второе, то метод может выглядеть вот так:
C#
1
2
3
4
5
6
7
8
9
10
11
        public static IEnumerable Where(this IEnumerable list, List<string> propertyNames, List<List<int>> IDs)
        {
            IEnumerable res = list;
            for (int i = 0; i < propertyNames.Count; i++)
            {
                var ii = i;
                res = res.Where<BaseDictionary>(propertyNames[ii], e => IDs[ii].Contains(e.ID));
            }
 
            return res;
        }
1
3 / 3 / 2
Регистрация: 30.07.2017
Сообщений: 223
09.04.2018, 14:11  [ТС]
Цитата Сообщение от Storm23 Посмотреть сообщение
Взаимоисключающие параграфы. Не?
Не. Предполагал, что смогу самостоятельно изменить логику работы метода, но Ваше решение получил быстрее. Спасибо!

Цитата Сообщение от Storm23 Посмотреть сообщение
На самом деле, даже сейчас есть неоднозначность - непонятно нужно отбирать по AND только среди тех свойств которые присутствуют в объекте, или же все свойства должны обязательно присутствовать в объекте.
Ну, я начинающий специалист ... Поэтому, лучшие решения приходят по ходу реализации.
Например, как мы уже определились, есть классы-справочники, скажем: A, B, C, D, E и т.д. Основные (фильтруемые) классы имеют свойства этих классов, например, класс MainClass1: A, B, D; MainClass2: B, C, D; MainClass3: B, D, E.
Изначально я предполагал, что я буду для каждого фильтруемого класса самостоятельно определять перечень классов (имен свойств) и их значений для фильтрации.
Но, сейчас я думаю - а зачем? Можно ведь всю коллекцию фильтров прогнать через некий универсальный метод и, если свойство данного класса-справочника у MainClass в наличии, то соответствующая коллекция отфильтруется, а если нет, то и не надо
Логично? Или это не очень эффективно?
И еще у меня второй вопрос по последнему коду:
Я понимаю, что присвоение
C#
1
var ii = i;
необходимо для того, чтобы не выйти за границы коллекции, но не понимаю как это работает (т.е. я бы, конечно, организовал это дополнительной проверкой if). Можете написать в двух словах или дать соответствующую ссылку?
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
09.04.2018, 17:42
Цитата Сообщение от wrq2017 Посмотреть сообщение
необходимо для того, чтобы не выйти за границы коллекции, но не понимаю как это работает (т.е. я бы, конечно, организовал это дополнительной проверкой if). Можете написать в двух словах или дать соответствующую ссылку?
Нет, это не для проверки выхода за границы. Это специфичная для C# проблема захвата локальной переменной лямбдами.
Если у вас лямбда внутри цикла, то нужно сделать копию переменной, перед тем, как передать ее в лямбду.
https://stackoverflow.com/ques... le_rich_qa
https://blogs.msdn.microsoft.c... d-harmful/

Добавлено через 7 минут
Цитата Сообщение от wrq2017 Посмотреть сообщение
Логично? Или это не очень эффективно?
Логично. Но тут другой вопрос - а нужно ли вам так много классов которые по сути просто являются контейнерами словарей? Может просто сделать один класс который внутри будет содержать список (в буквальном смысле List<Basedictionary>) в котором будут словари.
1
3 / 3 / 2
Регистрация: 30.07.2017
Сообщений: 223
10.04.2018, 16:55  [ТС]
Цитата Сообщение от Storm23 Посмотреть сообщение
Логично. Но тут другой вопрос - а нужно ли вам так много классов которые по сути просто являются контейнерами словарей? Может просто сделать один класс который внутри будет содержать список (в буквальном смысле List<Basedictionary>) в котором будут словари.
Нет, но я ведь немного упростил. Каждый MainClass представляет собой некую бизнес-сущность, с которой удобно работать именно в таком виде как есть, а не собирать разбитые по коллекциям справочники.

Добавлено через 7 часов 4 минуты
Storm23, с фильтрацией по свойствам-справочникам разобрались. А как сделать универсальный метод фильтрации по свойству типа DateTime (свойства могут называться по разному, название свойства будет параметром)?
Фильтрация должна быть вроде:
C#
1
2
3
4
DateTime MaxDate;
DateTime MinDate;
 
temp = temp.Where<T>("SomeDate", x => x.Date >= MinDate && x.Date. <= MaxDate);
Как это сделать? Все главные классы должны быть наследниками некоего класса (интерфейса?) реализующего основное свойство-дату?
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
10.04.2018, 19:16
Цитата Сообщение от wrq2017 Посмотреть сообщение
Как это сделать?
Я вам выше уже показывал пример фильтрации по дате. Это поддерживается методом where:
C#
1
tempMain = list.Where<DateTime>("Date", d => d > new DateTime(2018, 1, 1));
Цитата Сообщение от wrq2017 Посмотреть сообщение
Все главные классы должны быть наследниками некоего класса (интерфейса?) реализующего основное свойство-дату?
Не нужно никаких интерфейсов.
1
3 / 3 / 2
Регистрация: 30.07.2017
Сообщений: 223
11.04.2018, 09:56  [ТС]
Storm23, огромное спасибо!!! Я получил исчерпывающие ответы на вопросы по фильтрации (как я себе её представляю ). Будем считать тему закрытой.
0
3 / 3 / 2
Регистрация: 30.07.2017
Сообщений: 223
20.04.2018, 14:44  [ТС]
Storm23, поторопился я закрывать тему. Как обойти ошибку, если одно из свойств фильтруемого члена коллекции равно null?

Пример:
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApplication228
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> listAid = new List<int>() { 1 };
            List<int> listBid = new List<int>() { 2 };
            List<List<int>> allist = new List<List<int>>();
            allist.Add(listAid);
            allist.Add(listBid);
            var list = new List<SomeMainClass>()
            {
                new SomeMainClass {A = new A {ID = 1}, B = new B {ID = 2}, C = new C {ID = 3}},
                new SomeMainClass {A = new A {ID = 1}, B = null, C = new C {ID = 33 }},
                new SomeMainClass {A = new A {ID = 111}, B = new B {ID = 222}, C = new C {ID = 333 }}
            };
 
            var tempMain = list.Where(new List<string>() { "A", "B" }, allist);
 
            Show(tempMain);
 
 
            Console.ReadLine();
 
            //  
        }
 
        private static void Show(IEnumerable list)
        {
            Console.WriteLine("-----------");
            foreach (var item in list)
                Console.WriteLine(item);
        }
    }
 
    public static class FilterHelper
    {
        public static IEnumerable Where<T>(this IEnumerable list, string propertyName, Func<T, bool> filter)
        {
            foreach (var obj in list)
                if (obj != null)
                {
                    var pi = obj.GetType().GetProperty(propertyName);
                    if (pi != null)
                    {
                        if (pi.PropertyType == typeof(T) || pi.PropertyType.IsSubclassOf(typeof(T)))
                            if (filter((T)pi.GetValue(obj)))
                                yield return obj;
                    }
                    else
                    {
                        yield return obj;
                    }
                }
        }
 
 
 
        public static IEnumerable Where(this IEnumerable list, List<string> propertyNames, List<List<int>> IDs)
        {
            IEnumerable res = list;
            for (int i = 0; i < propertyNames.Count; i++)
            {
                var ii = i;
                res = res.Where<BaseDictionary>(propertyNames[ii], e => IDs[ii].Contains(e.ID) || IDs[ii][0] == 0);
            }
 
            return res;
        }
    }
 
    public class BaseDictionary
    {
        public int ID { get; set; }
        public string Description { get; set; }
    }
 
    public class A : BaseDictionary
    {
 
    }
    public class B : BaseDictionary
    {
 
    }
 
    public class C : BaseDictionary
    {
 
    }
 
    public class SomeMainClass
    {
        public A A { get; set; }
        public B B { get; set; }
        public C C { get; set; }
        public DateTime? SomeDate { get; set; }
        public override string ToString()
        {
            return string.Format("A: {0} B: {1} C: {2} Date: {3}", A.ID, B.ID, C.ID, SomeDate);
        }
    }
}
Добавлено через 39 секунд
По логике, такие члены нужно исключить из коллекции, пропустить их.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
21.04.2018, 11:12
Цитата Сообщение от wrq2017 Посмотреть сообщение
Как обойти ошибку, если одно из свойств фильтруемого члена коллекции равно null?
Ну так проверяйте на null:
Cтрока 73:

C#
1
res = res.Where<BaseDictionary>(propertyNames[ii], e => e != null && (IDs[ii].Contains(e.ID) || IDs[ii][0] == 0));
1
3 / 3 / 2
Регистрация: 30.07.2017
Сообщений: 223
28.04.2018, 09:48  [ТС]
Цитата Сообщение от Storm23 Посмотреть сообщение
Ну так проверяйте на null:
Так не работает, он всё равно пытается пробиться к e.ID, где e == null

Добавлено через 4 минуты
Ой, сорри, работает, ошибка в другом месте

Добавлено через 17 минут
Storm23, еще вопрос. Для фильтрации по датам используется следующая конструкция:
C#
1
2
3
4
5
6
7
8
9
10
11
12
            if (DateProperty == null) return res;
            if (Nullable)
            {
                res = res.Where<DateTime?>(DateProperty, e => e >= (DateTime?)Common.filters[FN.minDate].Value[0])
                         .Where<DateTime?>(DateProperty, e => e <= (DateTime?)Common.filters[FN.maxDate].Value[0]);
            }
            else
            {
                res = res.Where<DateTime>(DateProperty, e => e >= (DateTime)Common.filters[FN.minDate].Value[0])
                         .Where<DateTime>(DateProperty, e => e <= (DateTime)Common.filters[FN.maxDate].Value[0]);
            }
            return res;
Потому что некоторые даты Nullable, а некоторые нет. Можно это как-то упростить или обойти?
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
28.04.2018, 10:40
Цитата Сообщение от wrq2017 Посмотреть сообщение
Потому что некоторые даты Nullable, а некоторые нет. Можно это как-то упростить или обойти?
Вот так работает и с Nullable и с обычными типами:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        public static IEnumerable Where<T>(this IEnumerable list, string propertyName, Func<T, bool> filter)
        {
            foreach (var obj in list)
            if (obj != null)
            {
                var pi = obj.GetType().GetProperty(propertyName);
                if (pi != null)
                {
                    var val = pi.GetValue(obj);
                    if (val != null && val is T)
                    if (filter((T)val))
                        yield return obj;
                }
                else
                {
                    yield return obj;
                }
            }
        }
Вызывать с обычным (не Nullable) типом:

C#
1
res = res.Where<DateTime>(DateProperty, e => e >= (DateTime)Common.filters[FN.minDate].Value[0] && e <= (DateTime)Common.filters[FN.maxDate].Value[0]);
0
3 / 3 / 2
Регистрация: 30.07.2017
Сообщений: 223
28.04.2018, 12:54  [ТС]
Цитата Сообщение от Storm23 Посмотреть сообщение
Вызывать с обычным (не Nullable) типом:
А с Nullable? Так? :
C#
1
res = res.Where<DateTime?>(DateProperty, e => e >= (DateTime?)Common.filters[FN.minDate].Value[0] && e <= (DateTime?)Common.filters[FN.maxDate].Value[0]);
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
28.04.2018, 13:00
Цитата Сообщение от wrq2017 Посмотреть сообщение
А с Nullable? Так? :
И для nullable и для не nullable вызывать так:
C#
1
res = res.Where<DateTime>(DateProperty, e => e >= (DateTime)Common.filters[FN.minDate].Value[0] && e <= (DateTime)Common.filters[FN.maxDate].Value[0]);
PS Если нужно будет еще что нибудь повторить по нескольку раз - не стесняйтесь, спрашивайте.
0
3 / 3 / 2
Регистрация: 30.07.2017
Сообщений: 223
28.04.2018, 13:02  [ТС]
Цитата Сообщение от Storm23 Посмотреть сообщение
PS Если нужно будет еще что нибудь повторить по нескольку раз - не стесняйтесь, спрашивайте.
Сорри, из предыдущего сообщения не совсем было понятно, что вызов универсиализирован.
0
3 / 3 / 2
Регистрация: 30.07.2017
Сообщений: 223
21.06.2018, 13:41  [ТС]
Storm23, возвращаясь к вышеизложенному. Не могу никак победить такой случай. Если значение свойства null, то элемент коллекции тоже должен попадать в результат выборки (в случае если значение фильтра 0). Как это можно сделать?
И сопутствующий вопрос - почему при дебаге не осуществляется вход в метод Where?

Добавлено через 2 часа 44 минуты
Везде, где было != null поубирал по тексту, но всё равно результата нет.

Добавлено через 18 минут
Вот если убрать строку
C#
1
 if (val != null && val is T)
всё работает. Но что характерно, в таком виде:
C#
1
if (val is T)
не работает.
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
22.06.2018, 01:59
wrq2017,
Выложите полый пример, который можно откомпилировать.
Укажите где происходят проблемы.
0
3 / 3 / 2
Регистрация: 30.07.2017
Сообщений: 223
22.06.2018, 10:04  [ТС]
Storm23, да в принципе уже не важно Работает. Сейчас интересует второй, больше теоретический вопрос, если значение объекта null - значит ли это, что его тип невозможно определить?
0
 Аватар для Cupko
658 / 595 / 171
Регистрация: 17.07.2012
Сообщений: 1,682
Записей в блоге: 1
22.06.2018, 12:52
Цитата Сообщение от wrq2017 Посмотреть сообщение
Сейчас интересует второй, больше теоретический вопрос, если значение объекта null - значит ли это, что его тип невозможно определить?
null - это ссылка на несуществующий объект.
Тип несуществующего объекта определить невозможно, что логично.
Можно определить тип переменной, в которой хранится этот null.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.06.2018, 12:52
Помогаю со студенческими работами здесь

Не могу сделать чтобы класс содержал основной конструктор и конструктор копирования
Разработать класс ThreeAngle для работы с плоскими треугольниками. В качестве членов-данных задаются длины трех сторон треугольника. Класс...

Конструктор класса, конструктор копирования запускается не тот который нужен
Есть такой конструктор: Neuron::Neuron(int iType_activation_funk) { this-&gt;iType_act = iType_activation_funk; switch...

this(Всегда ли вызывается конструктор при не явной передачи объекта в конструктор)
class Test { int i; public: void test(int i) { this -&gt; i = i; } }; Конструктор Test::Test всегда вызывается...

Будет ли определен компилятором конструктор по умолчанию, если есть конструктор с дефолтным параметром?
Добрый день, сразу к делу, есть некий класс class some { int x; public: some(int y = 1) : x(y) {} };

Создать класс. Написать конструктор по умолчанию, конструктор с параметрами. Перегрузить операции «меньше» и «равно»
Помогите пожалуйста, хоть с одним из заданий. 1. Создать класс. Написать конструктор по умолчанию, конструктор с параметрами....


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

Или воспользуйтесь поиском по форуму:
38
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru