[英]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
您可以使用反射來獲取名為MyProperty
n的所有屬性,其中n MyProperty
1,然后可以使用PropertyInfo
的List
為填充的屬性計算位掩碼,並按該值分組。
首先,我使用一些擴展方法:
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.