假设我在运行时获得了一些像{ :type => 'X', :some_other_key => 'foo' }
这样的数据,并且根据某些条件,我想为它初始化相应的类。我们这样做是这样的。
TYPE_CLASSES = [
TypeA,
TypeB,
TypeC,
# ...
TypeUnknown
]
TYPE_CLASSES.detect {|type| type.responsible_for?(data)}.new
我们迭代一个类列表,并询问每个类是否负责给定数据并初始化找到的第一个类。
TYPE_CLASSES
的顺序很重要,而某些responsible_for?
方法不仅会检查类型,还会检查data
内的其他键。因此,对于type == 'B' && some_other_key == 'foo'
的一些专门的类检查必须在广义类检查type == 'B'
之前进行。
这很好用并且很容易扩展,但TYPE_CLASSES
列表已经很长了,所以在最坏的情况下找出正确的类型可能会导致迭代直到最后一个元素并为每个类型调用{{1检查。
有没有办法改善性能并避免迭代每个元素,同时仍保留支票的顺序?
答案 0 :(得分:1)
如果将数据集与类匹配就像您描述的那样复杂,那么使用决策树构建算法(example)可能是有意义的。
您可以使用AI4R library在Ruby中执行此操作。
可能您不需要动态构建该树。因此,您可以使用该库基本上为您生成优化的检测策略,例如文档:
DATA_LABELS = [ 'city', 'age_range', 'gender', 'marketing_target' ]
DATA_SET = [
['New York', '<30', 'M', 'Y'],
['Chicago', '<30', 'M', 'Y'],
['Chicago', '<30', 'F', 'Y'],
['New York', '<30', 'M', 'Y'],
['New York', '<30', 'M', 'Y'],
['Chicago', '[30-50)', 'M', 'Y'],
['New York', '[30-50)', 'F', 'N'],
['Chicago', '[30-50)', 'F', 'Y'],
['New York', '[30-50)', 'F', 'N'],
['Chicago', '[50-80]', 'M', 'N'],
['New York', '[50-80]', 'F', 'N'],
['New York', '[50-80]', 'M', 'N'],
['Chicago', '[50-80]', 'M', 'N'],
['New York', '[50-80]', 'F', 'N'],
['Chicago', '>80', 'F', 'Y']
]
id3 = ID3.new(DATA_SET, DATA_LABELS)
id3.get_rules
# => if age_range=='<30' then marketing_target='Y'
elsif age_range=='[30-50)' and city=='Chicago' then marketing_target='Y'
elsif age_range=='[30-50)' and city=='New York' then marketing_target='N'
elsif age_range=='[50-80]' then marketing_target='N'
elsif age_range=='>80' then marketing_target='Y'
else raise 'There was not enough information during training to do a proper induction for this data element' end
(所以你基本上可以把最后一行插入你的代码中。)
你需要选择足够的已经分类的记录来制作DATA_SET和DATA_LABELS,你还需要将你的哈希值转换为数组(这并不困难 - 基本上你的哈希键是DATA_LABELS
,您的哈希值是DATA_SET
数组的值。
当您添加新的TYPE_CLASS
时,只需重试“教学”即可。并更新您的检测代码。