Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linq 如何按属性以递归方式批处理集合_Linq_Parallel Processing - Fatal编程技术网

Linq 如何按属性以递归方式批处理集合

Linq 如何按属性以递归方式批处理集合,linq,parallel-processing,Linq,Parallel Processing,我正在尝试提出一种算法,给定一个包含子对象和“AlarmCount”属性的对象集合,该算法会将该集合拆分为平衡的批,以便并行处理 例如: public class AlarmElement { public int Id { get; set; } public IEnumerable<AlarmElement> Children { get; set; } public int AlarmCount { get; set;

我正在尝试提出一种算法,给定一个包含子对象和“AlarmCount”属性的对象集合,该算法会将该集合拆分为平衡的批,以便并行处理

例如:

    public class AlarmElement
    {
       public int Id { get; set; }
       public IEnumerable<AlarmElement> Children { get; set; }
       public int AlarmCount { get; set; }
    }

    var list = new List<AlarmElement>();
    list.Add(new AlarmElement { Id = 1, AlarmCount = 10, Children = new List<AlarmElement> { new AlarmElement { AlarmCount = 10 } } });
    list.Add(new AlarmElement { Id = 2, AlarmCount = 5, Children = new List<AlarmElement> { new AlarmElement { AlarmCount = 5 } } });
    list.Add(new AlarmElement { Id = 3, AlarmCount = 5, Children = new List<AlarmElement> { new AlarmElement { AlarmCount = 5 } } });
公共类报警元素
{
公共int Id{get;set;}
公共IEnumerable子项{get;set;}
公共int AlarmCount{get;set;}
}
var list=新列表();
添加(新的AlarmElement{Id=1,AlarmCount=10,子元素=new list{new AlarmElement{AlarmCount=10}});
添加(新的AlarmElement{Id=2,AlarmCount=5,子元素=new list{new AlarmElement{AlarmCount=5}}});
添加(新的AlarmElement{Id=3,AlarmCount=5,子元素=new list{new AlarmElement{AlarmCount=5}}});
该函数将返回2个集合,一个带有AlarmElement 1(20个报警),另一个带有AlarmElement 2和3(20个报警)

关于实现这一目标的最有效方法有什么想法吗?

好问题:)

我已经为这个问题编写了一个初始解决方案,将第一个列表拆分为两个列表,每个列表的总量接近另一个列表

    public class AlarmElement
    {
        public int Id { get; set; }
        public IEnumerable<AlarmElement> Children { get; set; }
        public int AlarmCount { get; set; }
    }

    class Grouped
    {
        public int Total { get; set; }
        public AlarmElement Alarm { get; set; }
    }

    int Count(AlarmElement element)
    {
        if (element == null) return 0;

        return element.AlarmCount + Count(element.Children);
    }

    int Count(IEnumerable<AlarmElement> elements)
    {
        if (elements == null || elements.Count() == 0)
        {
            return 0;
        }

        int count = 0;

        foreach (AlarmElement alarm in elements)
        {
            count += Count(alarm);
        }

        return count;
    }
公共类报警元素
{
公共int Id{get;set;}
公共IEnumerable子项{get;set;}
公共int AlarmCount{get;set;}
}
班级分组
{
公共整数总计{get;set;}
公共AlarmElement报警{get;set;}
}
整数计数(报警元素)
{
if(element==null)返回0;
返回element.AlarmCount+计数(element.Children);
}
整数计数(IEnumerable元素)
{
if(elements==null | | elements.Count()==0)
{
返回0;
}
整数计数=0;
foreach(报警元件报警元件)
{
计数+=计数(报警);
}
返回计数;
}
因此,这些只是一个助手类和两个计算每个AlarmElement子元素的方法

Split方法获取一个集合及其平均值,并将其拆分为围绕该平均值的两个集合:

    private void Split(IEnumerable<Grouped> alarms, double avg, 
        out IEnumerable<AlarmElement> firstAlarms, 
        out IEnumerable<AlarmElement> secondAlarms)
    {
        firstAlarms = 
            alarms
            .Where(a => a.Total < avg)
            .Select(a => a.Alarm);

        secondAlarms =
             alarms
            .Where(a => a.Total > avg)
            .Select(a => a.Alarm);
    }
private void Split(IEnumerable报警、双平均、,
发出无数的警报,
输出(可数秒报警)
{
第一次警报=
警报
.式中(a=>a.总计<平均值)
.选择(a=>a.报警);
二次警报=
警报
.其中(a=>a.总计>平均值)
.选择(a=>a.报警);
}
这是您发送初始报警列表的入口点:

    public IEnumerable<IEnumerable<AlarmElement>> GetBalanced(List<AlarmElement> list)
    {            
        var alarms =
            list
            .Select(a => new Grouped { Total = Count(a), Alarm = a });

        var avg = alarms.Average(a => a.Total);

        var result = new List<IEnumerable<AlarmElement>>();

        IEnumerable<AlarmElement> firstAlarms;               

        IEnumerable<AlarmElement> secondAlarms;

        Split(alarms, avg, out firstAlarms, out secondAlarms);

        result.Add(firstAlarms);
        result.Add(secondAlarms);

        return result;
    }
public IEnumerable GetBalanced(列表)
{            
无功报警=
列表
.选择(a=>新分组{Total=Count(a),报警=a});
var avg=报警。平均值(a=>a.总计);
var result=新列表();
i数不清的警报;
i可数秒报警;
拆分(报警、平均值、输出第一报警、输出第二报警);
结果。添加(第一次报警);
结果。添加(第二次报警);
返回结果;
}
正如我提到的,它只是一个开端,因为您可以通过在每个部分上递归使用Split方法来进一步增强它,直到您满意为止