有没有办法在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另一个。
答案 0 :(得分:1)
将您的表UNPIVOT更改为以下内容:
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
答案 1 :(得分:1)
您可以使用反射来获取名为MyProperty
n的所有属性,其中n为1,然后使用List
s中的PropertyInfo
来计算以下项的位掩码:填充的属性,然后按该值分组。
首先我使用一些扩展方法:
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);
如果第一个属性不是以整数结尾,则需要测试以按顺序处理它,或者(特别是如果这些属性不是全部以数字结尾),则可以省略{{ 1}}并使用OrderBy
返回的任何顺序-顺序并不重要。对于每种有价值的属性组合,返回的答案都是GetProperties
,其中IGrouping
的位掩码显示了哪些属性被重视。
如果您拥有31个以上的属性,则应切换为使用Key
并创建明显的long
扩展方法(LongPow
)。