簡體   English   中英

如何使用多個條件在LINQ中進行分組?

[英]How do I group by in LINQ using multiple criteria?

有沒有辦法獲得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的所有組合,以及只有一個屬性具有value且其他屬性為零的所有組合,等等。

到目前為止,我有這樣的事情:

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或為空,則不會將該值添加到查詢中。 我希望獲得具有相同模式的所有組合,以便能夠將具有相同模式的所有項目放入SQL中的IN中。

輸出數據將如下所示:

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另一個。

將您的表取消注釋,如下所示:

 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演示

您可以使用反射來獲取名為MyProperty n的所有屬性,其中n MyProperty 1,然后可以使用PropertyInfoList為填充的屬性計算位掩碼,並按該值分組。

首先,我使用一些擴展方法:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM