我想针对特定问题开发一种自我训练算法。为了简单起见,我将把它归结为简单的例子。
更新:我添加了一个工作解决方案作为下面这个问题的答案。
假设我有来自数据库的大量实体列表。每个实体都是相同的类型,并且有 4 个字节类型的属性。
public class Entity
{
public byte Prop1 { get; set; }
public byte Prop2 { get; set; }
public byte Prop3 { get; set; }
public byte Prop4 { get; set; }
}
现在我想根据一个简单的条件动态测试每个实体的一个或多个属性。这基本上意味着我想针对这种条件测试所有属性的所有可能组合。
为了完成此任务,我为属性创建了一个位掩码。
[Flags]
public enum EEntityValues
{
Undefined = 0,
Prop1 = 1,
Prop2 = 2,
Prop3 = 4,
Prop4 = 8,
}
并添加了一种获取位掩码最大值的方法。对于本示例,返回 15 (1 + 2 + 4 + 8)。
public static int GetMaxValue<T>() where T : struct
{
return Enum.GetValues( typeof(T) ).Cast<int>().Sum();
}
在此阶段,我可以使用简单的循环迭代所有属性组合。在示例中,在第一次迭代中测试属性 Prop1,在第二次迭代中测试属性 Prop2,在第三次迭代中测试属性 Prop1 和 Prop2,依此类推。
for(int i = 1; i <= GetMaxValue<EEntityValues>(); i++)
{
EEntityValues flags = (EEntityValues)i;
if(flags.HasSet(EEntityValues.Prop1))
{
....
}
}
现在让我们将实体放入游戏中。
List<Entity> entities = GetEntitiesFromDb();
for(int i = 1; i <= GetMaxValue<EEntityValues>(); i++)
{
EEntityValues flags = (EEntityValues)i;
byte minProp1Value = 10, minProp2Value = 20, minProp3Value = 30, minProp4Value = 40;
foreach(Entitiy entity in entities)
{
if(flags.HasSet(EEntityValues.Prop1) && entitiy.Prop1 >= minProp1Value)
{
....
} else { continue; }
if(flags.HasSet(EEntityValues.Prop2) && entitiy.Prop2 >= minProp2Value)
{
....
} else { continue; }
}
}
好吧,如果我的最小值是静态的,这非常有效。
现在让我们变得更复杂。我们记得,在第一次迭代中,我们仅测试属性 Prop1,因为位掩码为 1。Prop1 的值范围是 0..255。我还为此属性定义了一个最小值,其有效范围为 1..255。这个最小值只是一个过滤器,用于跳过 foreach 循环中的实体。
现在我想在提高最低水平的同时测试属性 Prop1。这些测试不是问题的一部分,因此我没有将它们包含在我的样本中。
byte minProp1Value = 1;
while(minProp1Value <= 255)
{
foreach(Entitiy entity in entities)
{
if(flags.HasSet(EEntityValues.Prop1) && entitiy.Prop1 >= minProp1Value)
{
.... // Testing the matching entity and storing the result
} else { continue; }
}
minProp1Value++;
}
这对于单一财产来说很简单。在第三次迭代中,我必须处理 2 个属性,Prop1 和 Prop2,因为位掩码是 3。
byte minProp1Value = 1, minProp2Value = 1;
while(minProp1Value <= 255)
{
while(minProp2Value <= 255)
{
foreach(Entitiy entity in entities)
{
....
}
minProp2Value++;
}
minProp1Value++;
minProp2Value = 1;
}
正如您所看到的,在这个阶段,我正在根据不断上升的最低级别测试每个实体的 Prop1 和 Prop2。
由于我正在处理动态生成的多个属性集,因此我无法将 while 循环硬编码到我的代码中。这就是为什么我正在寻找一种更智能的解决方案来测试给定属性集(位掩码)的最小值的所有可能组合。