我正在尝试比较像这样的对象列表中的所有可能值:
public class Object21
{
int Id,
bool firstbool,
bool secondbool
}
我会遍历对象并将它们比作:
List<Object1> objects;
foreach(var o in objects)
{
if(firstbool && secondbool)
....
if(firstbool && !secondbool)
....
if(!firstbool && secondbool)
....
if(!firstbool && !secondbool)
....
}
这似乎没问题,但是如果对象有几个你在if语句中运行的值。
public class Object2
{
int Id;
int firstbool;
....
int twentiethbool;
}
然后你必须写出所有可能的条件语句,你的代码写得非常难以阅读。
List<Object2> objects2;
foreach(var o in objects2)
{
if(firstbool && secondbool && ... && twentiethbool)
....
if(....)
....
....
....
if(!firstbool && !secondbool && ... && !twentiethbool)
....
}
是否有更简单的方法来编写第二个场景,以便您不编写if语句的每个组合?
最后,我想计算列表中每个条件的出现百分比。
答案 0 :(得分:3)
回答问题的第一部分(关于比较每个组合):
除了写一堆if语句之外,除此之外没有其他方法可行。当然;你可能不应该这样做:)
你可能会使用反射和递归,但那会很快弄乱 。
幸运的是,要获得每个标志的百分比,您可以这样做:
list.Count(i => i.firstbool) / (double)list.Count();
...
答案 1 :(得分:0)
首先,创建一个字典以保存所有条件
var dict = new Dictionary<string, int>{{"001",0},{"010",0} ...}
然后,创建关键用途bool值
var key=string.Empty;
key+=firstbool ?"0":"1"
key+=secondbool ?"0":"1"
......
毕竟,你可以知道发生了哪种情况
dict[key]++;
答案 2 :(得分:0)
给出这样的类结构:
public class YourClass
{
public int Id { get; set; }
public bool firstbool { get; set; }
public bool secondbool { get; set; }
public bool thirdbool { get; set; }
}
您可以使用反射来获取类中的所有布尔值(以及仅bool值):
public IEnumerable<bool> GetBools(YourClass obj)
{
return obj.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(x => x.PropertyType == typeof (bool))
.Select(x => (bool)x.GetValue(obj, null));
}
然后使用LINQ迭代集合,并创建组合和总计字典:
List<YourClass> objects = new List<YourClass>();
var totals = objects.GroupBy(x => String.Join(",", GetBools(x)))
.ToDictionary(x => x.Key, x => x.Count() / (double)objects.Count);
这将为您提供一个字典,其中包含每个唯一组合及其出现的百分比。
鉴于此输入:
var o = new List<YourClass>
{
new YourClass {firstbool = true, secondbool = true, thirdbool = false},
new YourClass {firstbool = false, secondbool = false, thirdbool = false},
new YourClass {firstbool = true, secondbool = true, thirdbool = false}
};
字典中的结果将是:
{["True,True,False", 0.666666666666667]}
{["False,False,False", 0.333333333333333]}
答案 3 :(得分:0)
重写你的类可能更容易,将每个条件存储在一个数组中,如下所示:
public class MyObject
{
public static int numFields = 20;
public enum Conditions
{
C1, C2, C3, .... C20 //name for each condition, so can set values using descriptive names
};
public Boolean[] BinaryFields = new Boolean[numFields];
public void setCondition(Conditions condition, Boolean value)
{
BinaryFields[(int)condition] = value;
}
public override string ToString()
{
return string.Join(",", BinaryFields);
}
}
然后你可以通过计算实际存在的内容来计算统计数据,而不是计算所有2 ^ 20种可能性。如下所示:
static void Main(string[] args)
{
//simulation: creat 10 MyObjects
List<MyObject> lst = new List<MyObject>();
for (int i = 0; i < 10; i++)
{
MyObject m = new MyObject();
//example of setting condition
m.setCondition(MyObject.Conditions.C1, true);
lst.Add(m);
}
//calculate stat
var resultCount = new Dictionary<string, int>(); //conditionResult, count
foreach (MyObject m in lst)
{
if (resultCount.ContainsKey(m.ToString()))
{
resultCount[m.ToString()] += 1;
}
else
{
resultCount.Add(m.ToString(), 1);
}
}
//print stat
foreach(KeyValuePair<string, int> entry in resultCount){
Debug.WriteLine("probability for conditoin={0} is {1}", entry.Key, (double)entry.Value / lst.Count);
}
}
答案 4 :(得分:0)
如果你对每个布尔属性组合有一些独特的动作,我建议你为你的对象使用某种字符串键,在这些值上生成。像"001001"
,"000000"
等等。然后使用Dictionary<string, Func<int>>
来保存所有独特的操作,通过它的键获取并执行正确的操作。例如:
public class Object21
{
public int Id { get; set; }
public bool FirstBool { get; set; }
public bool SecondBool { get; set; }
public bool ThirdBool { get; set; }
public bool FourthBool { get; set; }
public bool FifthBool { get; set; }
public bool SixthBool { get; set; }
public void Process()
{
// Perform the action
Actions[Key]();
}
// Returns "001001" like representation of your object
public string Key
{
get
{
return string.Join(string.Empty, GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(x => x.PropertyType == typeof(bool))
.Select(x => (bool)x.GetValue(this, null) ? "1" : "0" ));
}
}
private static Dictionary<string, Func<int>> Actions
{
get
{
return new Dictionary<string, Func<int>>
{
{"000000", new Func<int>(delegate
{
Console.WriteLine("000000 action performed.");
return 0;
})},
{"000001", new Func<int>(delegate
{
Console.WriteLine("000001 action performed.");
return 1;
})},
{"000010", new Func<int>(delegate
{
Console.WriteLine("000010 action performed.");
return 2;
})},
// More actions
{"111111", new Func<int>(delegate
{
Console.WriteLine("111111 action performed.");
return 63;
})}
};
}
}
}
然后在你的程序中使用它:
static void Main(string[] args)
{
var list = new List<Object21>
{
// initialize your list
};
foreach (var object21 in list)
{
object21.Process();
}
// Calculate your occurrences (basically what @Grant Winney suggested)
var occurrences = list.GroupBy(o => o.Key).ToDictionary(g => g.Key, g => (g.Count() / (double)list.Count)*100);
foreach (var occurrence in occurrences)
{
Console.WriteLine("{0}: {1}%", occurrence.Key, occurrence.Value);
}
}