我真的在想如何去做,如果可能的话,但似乎我被困住了。
我有些东西
public class Obj
{
public bool Allow { get; set;}
public bool Forbidden { get; set; }
public bool Forgotten { get; set; }
}
并且我有list<;obj>
,列表中的所有对象都必须组合在单个obj
中,如果这些对象中的属性为true
,则应将其设置为true
,否则将其保留为false
。
例如。
List<Obj> list = new List<Obj>()
{
new Obj() { Allow = false, Forbidden = false, Forgotten = true },
new Obj() { Allow = true, Forbidden = false, Forgotten = false },
new Obj() { Allow = false, Forbidden = false, Forgotten = true }
}
在这种情况下,我将获得新的obj
,其值为allow=true(在其中一个对象中,它被设置为true),baidund=false,goldget=true(有一个对象的这个属性也被设置为true)
这是否可以在不执行多个.where()
的情况下以优雅的方式实现?
这应该会起作用:
public Obj CoalesceObjs(IEnumerable<Obj> items)
{
var result = new Obj();
foreach(var item in items)
{
result.Allow = result.Allow || item.Allow;
result.Forbidden = result.Forbidden || item.Forbidden;
result.Forgotten = result.Forgotten || item.Forgotten;
}
return result;
}
如果您真的想使用linq,也可以这样做:
var seed = new Obj();
list.Aggregate(seed, (cur, next) => {
cur.Allow = cur.Allow || next.Allow;
cur.Forbidden = cur.Forbidden || next.Forbidden;
cur.Fogotten = cur.Forgotten || next.Forgotten;
return cur;
});
//seed is now also the result
我可以再次将其包装在函数中,如下所示:
public Obj CoalesceObjs(IEnumerable<Obj> items)
{
var seed = new Obj();
return list.Aggregate(seed, (cur, next) => {
cur.Allow = cur.Allow || next.Allow;
cur.Forbidden = cur.Forbidden || next.Forbidden;
cur.Fogotten = cur.Forgotten || next.Forgotten;
return cur;
});
}
如果性能无关紧要,那么一个真正优雅,真正易于阅读的方法是:
Obj result = new Obj()
{
Allow = list.Any(o => o.Allow),
Forbidden = list.Any(o => o.Forbidden),
Forgotten = list.Any(o => o.Forgotten)
};
请注意,您正在查询列表3次,为了获得性能更好的解决方案,您可以使用LINQsaggrege
。 但这实际上取决于第一个true
出现的位置。
我实际上是用反射实现的,因为我不想在新属性出现时添加相关属性
public static T MergeInSingleObjectBool<T>(this List<T> list)
where T : new()
{
var obj = new T();
foreach (var item in list)
{
var type = item.GetType();
foreach (var prop in type.GetProperties())
{
var name = prop.Name;
var value = (bool)type.GetProperty(name).GetValue(item);
if (value)
{
obj.GetType().GetProperty(name).SetValue(obj, value);
}
}
}
return obj;
}