我正在尝试提出一种算法,该算法给出了带子项的对象集合,“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 } } });
该函数将返回2个集合,一个带有AlarmElement 1(20个警报),另一个带有AlarmElement 2和3(20个警报)。
有关实现这一目标的最有效方法的任何想法?
答案 0 :(得分:0)
好问题:)
我已经为这个问题编写了一个启动解决方案,将第一个列表拆分为2个列表,每个列表的总量接近另一个列表。
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;
}
所以那些只是一个辅助类和2个计算每个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);
}
这是您发送初始警报列表的入口点:
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;
}
正如我所提到的,它只是一个启动器,因为您可以通过在每个部件上递归使用Split方法来进一步增强它,直到您满意为止。