C# 中具有自定义集合的元素指标
本文关键字:元素 集合 自定义 | 更新日期: 2023-09-27 18:31:22
我正在尝试找出组织一堆数据类的最佳方式,因为我需要能够在某个时候访问它们的一些指标。
这是我的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 集合,并并排比较它们是否存在任何差异(它们应该是相同的)。我希望能够首先在这个更高的级别上比较他们的指标,然后细分他们之间的确切差异。
感谢您对如何实现这一目标的任何了解。
。"收集"数以千计的这些
数千人并不是一个很大的数字。只需使用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());
使用 Linq 的现有答案绝对很棒而且非常优雅,所以下面提出的想法只供后人参考。
这是一个(非常粗略的)基于反射的程序,它将引导您计算任何对象集合中的"有效"属性。
验证器由您在验证器字典中定义,以便您可以轻松更改每个属性的有效/无效值。如果您最终得到的对象具有大量属性,并且不想为每个属性在实际集合本身上编写内联 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();
}
}
}
可以使用以下 linq 查询获取标题计数:
int titleCount = ORCollection
.Where(x => !string.IsNullOrWhiteSpace(x.title))
.Count();
您可以像这样获得关闭的计数:
int closedCount = ORCollection
.Where(x => x.status == status.CLOSED)
.Count();
如果您要拥有更大的集合或经常访问值,则可能值得创建一个存储字段计数的自定义集合实现,然后它可以在添加和删除项目时递增/递减这些值。您还可以在此自定义集合中存储状态计数字典,该字典会在您添加和删除项目时更新。