3

我正在尝试找出组织一堆数据类的最佳方法,因为我需要能够在某个时候访问它们的一些指标。

这是我的 OR 课程的片段:

public enum status { CLOSED, OPEN }

public class OR
{
    public string reference { get; set; }
    public string title { get; set; }
    public status status { get; set; }
}

并非我初始化的每个 OR 都具有所有属性的值。我希望能够以这样一种方式将数千个这些“收集”在一起,以便我可以轻松地获得有多少 OR 对象具有值集的计数。例如:

OR a = new OR() { reference = "a" }
OR b = new OR() { reference = "b", title = "test" }
OR c = new OR() { reference = "c", title = "test", status = status.CLOSED }

现在这些以某种我可以做的方式收集(伪):

int titleCount = ORCollection.titleCount;
titleCount = 2

我还希望能够收集枚举类型属性的指标,例如Dictionary从集合中检索一个看起来像:

Dictionary<string, int> statusCounts = { "CLOSED", 1 }

想要访问这些指标的原因是我正在构建两个 OR 集合并并排比较它们是否存在差异(它们应该是相同的)。我希望能够先在这个更高级别比较他们的指标,然后再细分它们的不同之处。

感谢您提供有关如何完成此任务的任何信息。:-)

4

3 回答 3

3

...“收集”数千个这样的

数千并不是一个庞大的数字。只需使用 a List<OR>,您就可以通过 Linq 查询获取所有指标。

例如:

List<OR> orList = ...;

int titleCount = orList
       .Where(o => ! string.IsNullOrEmpty(o.title))
       .Count(); 

Dictionary<status, int> statusCounts = orList
        .GroupBy(o => o.status)
        .ToDictionary(g => g.Key, g => g.Count());
于 2013-09-16T07:43:00.320 回答
2

使用 Linq 的现有答案绝对很棒而且非常优雅,所以下面提出的想法只是为了后代。

这是一个(非常粗略的)基于反射的程序,它可以让您计算任何对象集合中的“有效”属性。

验证器由您在 Validators 字典中定义,以便您可以轻松更改每个属性的有效/无效值。如果您最终得到具有大量属性的对象并且不想为每个属性在实际集合本身上编写内联 linq 指标,您可能会发现它作为一个概念很有用。

您可以将其武器化为一个函数,然后针对两个集合运行它,从而为您报告两者之间的确切差异提供基础,因为它记录了对最终字典中各个对象的引用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace reftest1
{
    public enum status { CLOSED, OPEN }

    public class OR 
    {
        public string reference { get; set; }
        public string title { get; set; }
        public status status { get; set; }
        public int foo { get; set; }

    }

    //creates a dictionary by property of objects whereby that property is a valid value
    class Program
    {

        //create dictionary containing what constitues an invalid value here
        static Dictionary<string,Func<object,bool>> Validators = new Dictionary<string, Func<object,bool>>
            {

                {"reference", 
                    (r)=> { if (r ==null) return false;
                              return !String.IsNullOrEmpty(r.ToString());}
                },
                {"title",
                    (t)=> { if (t ==null) return false;
                              return !String.IsNullOrEmpty(t.ToString());}
               }, 
               {"status", (s) =>
                    {
                        if (s == null) return false;
                        return !String.IsNullOrEmpty(s.ToString());
              }},
             {"foo",
                 (f) =>{if (f == null) return false;
                            return !(Convert.ToInt32(f.ToString()) == 0);}
                    }
            };

        static void Main(string[] args)
        {
            var collection = new List<OR>();
            collection.Add(new OR() {reference = "a",foo=1,});
            collection.Add(new OR(){reference = "b", title = "test"});
            collection.Add(new OR(){reference = "c", title = "test", status = status.CLOSED});

            Type T = typeof (OR);
            var PropertyMetrics = new Dictionary<string, List<OR>>();
            foreach (var pi in GetProperties(T))
            {
                PropertyMetrics.Add(pi.Name,new List<OR>());
                foreach (var item in collection)
                {
                    //execute validator if defined
                    if (Validators.ContainsKey(pi.Name))
                    {
                       //get actual property value and compare to valid value
                       var value = pi.GetValue(item, null);
                       //if the value is valid, record the object into the dictionary
                       if (Validators[pi.Name](value))
                       {
                           var lookup = PropertyMetrics[pi.Name];
                           lookup.Add(item);
                       }
                    }//end trygetvalue
                }
            }//end foreach pi
            foreach (var metric in PropertyMetrics)
            {
                Console.WriteLine("Property '{0}' is set in {1} objects in collection",metric.Key,metric.Value.Count);
            }
            Console.ReadLine();
        }


        private static List<PropertyInfo> GetProperties(Type T)
        {
            return T.GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();
        }
    }
}
于 2013-09-16T08:32:23.550 回答
1

您可以使用此 linq 查询获取标题计数:

int titleCount = ORCollection
                    .Where(x => !string.IsNullOrWhiteSpace(x.title))
                    .Count();

你可以像这样得到关闭的计数:

int closedCount = ORCollection
                     .Where(x => x.status == status.CLOSED)
                     .Count();

如果您要拥有更大的集合或大量访问这些值,则可能值得创建一个存储字段计数的自定义集合实现,然后它可以在您添加和删除项目时增加/减少这些值。您还可以在此自定义集合中存储状态计数字典,该字典会随着您添加和删除项目而更新。

于 2013-09-16T07:55:00.180 回答