提问者:小点点

使用bool属性将相同对象列表合并为单个对象C#


我真的在想如何去做,如果可能的话,但似乎我被困住了。

我有些东西

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()的情况下以优雅的方式实现?


共3个答案

匿名用户

这应该会起作用:

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;
    }