Как мне сгруппировать в LINQ, используя несколько критериев? - PullRequest
0 голосов
/ 07 мая 2019

Есть ли способ получить все возможные комбинации в ObservableCollection?

У меня есть такая модель:

    public string MyProperty { get; set; }
    public string MyProperty2 { get; set; }
    public string MyProperty3 { get; set; }
    public string MyProperty4 { get; set; }
    public string MyProperty5 { get; set; }
    public string MyProperty6 { get; set; }
    public string MyProperty7 { get; set; }
    public string MyProperty8 { get; set; }

И я заполняю эту модель данными из электронной таблицы,но некоторые значения имеют нулевые или пустые значения (которые мне нужно исключить).Есть ли способ получить все возможные комбинации с одним и тем же шаблоном?

Например, все комбинации со значениями, отличными от 0, во всех свойствах и все комбинации, когда есть только одно свойство со значением иостальные ноль и т. д.

Пока у меня есть что-то вроде этого:

var group1 = _sourceStructure.Where(c => c.MyProperty != "0" && c.MyProperty2 != "0" && c.MyProperty3 != "0" && c.MyProperty4 != "0"
        && c.MyProperty5 != "0" && c.MyProperty6 != "0" && c.MyProperty7 != "0" && c.MyProperty8 != "0");

Но с этим мне нужно использовать более 30 случаев для оценки, есть ли способ получить всевозможные комбинации с использованием LINQ или другого решения?

Я хочу создать запрос SQL со значениями из коллекции, но если значение имеет значение 0 или пусто, я не добавлю это значение в запрос.Я хочу получить все комбинации с одинаковым шаблоном, чтобы можно было поместить все элементы с одинаковым шаблоном в IN в SQL.

Выходные данные будут выглядеть примерно так:

string query = @"Select field1, field2, field3, fieldn FROM table WHERE "

query = query + "field1 = " + _sourceStructure.MyProperty1;

query = query + "fieldN =  " + _sourceStructure.MyPropertyN;

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

Пример данных из исходного файла в Excel:

       MyProperty1 MyPropert2 MyPropertN
Row1      0          1           3
Row2      2          0           6
Row3      0          5           9
Row4      9          9           4
Row5      4          3           6
Row6      0          0           0

Вот, например, я ожидаючто Row1 и Row3 будут в одной группе (значения не одинаковы, но «структура» одинакова), а затем Row4 и Row5 будут другой группой, Row6 другой, а Row2 другой.

Ответы [ 2 ]

1 голос
/ 08 мая 2019

Вы можете использовать отражение, чтобы получить все свойства с именем MyProperty n, где n равно 1, а затем вы можете использовать List из PropertyInfo s, чтобы вычислить битовую маску для заполненных свойств, и сгруппироватьпо этому значению.

Сначала некоторые методы расширений, которые я использую:

public static class StringExt {
    public static string Past(this string s, string starter) {
        var starterPos = s.IndexOf(starter);
        return starterPos == -1 ? String.Empty : s.Substring(starterPos + starter.Length);
    }
}

public static class NumericExt {
    public static int ToInt<T>(this T obj) => Convert.ToInt32(obj);

    public static int IntPow(this int x, int pow) {
        int ans = 1;

        while (pow != 0) {
            if ((pow & 0x1) == 1)
                ans *= x;
            x *= x;
            pow >>= 1;
        }
        return ans;
    }
}

Теперь вы можете собрать интересующие свойства, отсортировать, а затем вычислить битовую маску для каждой строки:

var myPropInfos = typeof(COC).GetProperties()
                             .Where(pi => pi.Name.StartsWith("MyProperty"))
                             .OrderBy(pi => pi.Name.Past("MyProperty").ToInt()) // just in case properties aren't ordered
                             .ToList();
var GroupedFilters = src.Select(r => new { r, ValuedMask = myPropInfos.Select((pi, p) => pi.GetValue(r).ToString() != "0" ? 2.IntPow(p) : 0).Sum() })
                        .GroupBy(rm => rm.ValuedMask, rm => rm.r);

Если первое свойство не заканчивается целым числом, вам понадобится тест, чтобы обработать его при упорядочении или, альтернативно, (особенно если свойства не все заканчиваются числом), вы можете опуститьOrderBy и используйте любой порядок возврата GetProperties - порядок не имеет значения.Возвращаемый ответ - IGrouping для каждой комбинации оцененных свойств, с Key битовой маской, показывающей, какие свойства были оценены.

Если у вас более 31 свойства, вам следует перейти на использование longи создайте очевидный LongPow метод расширения (2L.LongPow(p) : 0L).

1 голос
/ 07 мая 2019

ОТКЛЮЧИТЕ вашу таблицу примерно так:

 Observable     Property      Value
     A             1            0
     A             2            1
     A             3            2
     B             1            0
     B             2            0
     B             3            1
     C             1            1
     C             2            2
     C             3            3

Все комбинации со значениями, отличными от 0, во всех свойствах:

SELECT Observable
FROM Table
GROUP BY Observable
HAVING SUM(CASE WHEN VALUE = 0 THEN 1 ELSE 0 END) = 0

Все комбинации, когда есть только одинсвойство со значением и остальные ноль:

SELECT Observable
FROM Table
GROUP BY Observable
HAVING COUNT(CASE WHEN VALUE > 0 THEN 1 END) = 1

SQL DEMO

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