如何比较对象中的所有值而不重复if语句?

时间:2014-11-19 01:36:45

标签: c#

我正在尝试比较像这样的对象列表中的所有可能值:

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语句的每个组合?

最后,我想计算列表中每个条件的出现百分比。

5 个答案:

答案 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);
    }
}