检查配置以确保每个规则都是唯一的更好方法

时间:2014-09-24 22:00:45

标签: python django dictionary

我有一个configs字典(由用户定义为Django应用程序的设置)。

我需要检查配置以确保它符合规则。

规则很简单。 '范围'每个选项中必须是唯一的。

样本设置

breakpoints = {
    'small': {
        'verbose_name': _('Small screens'),
        'min_width': None,
        'max_width': 640,
    },
    'medium': {
        'verbose_name': _('Medium screens'),
        'min_width': 641,
        'max_width': 1024,
    },
    'large': {
        'verbose_name': _('Large screens'),
        'min_width': 1025,
        'max_width': 1440,
    },
    'xlarge': {
        'verbose_name': _('XLarge screens'),
        'min_width': 1441,
        'max_width': 1920,
    },
    'xxlarge': {
        'verbose_name': _('XXLarge screens'),
        'min_width': 1921,
        'max_width': None,
    }
}

到目前为止,我所拥有的是什么。它有效,但似乎不是pythonic。

for alias, config in breakpoints.items():
    for alias2, config2 in breakpoints.items():
        if not alias2 is alias:
            msg = error_msg % (alias, 'breakpoint clashes with %s breakpoint' % alias2)
            for attr in ('min_width', 'max_width', ):
                if config[attr] is not None:
                    if (config2['min_width'] and config2['max_width']) and \
                            (config2['min_width'] <= config[attr] <= config2['max_width']):
                        raise ImproperlyConfigured(msg)
                    elif (config2['min_width'] and not config2['max_width']) and \
                            (config2['min_width'] < config[attr]):
                        raise ImproperlyConfigured(msg)
                    elif (config2['max_width'] and not config2['min_width']) and \
                            (config2['max_width'] > config[attr]):
                        raise ImproperlyConfigured(msg)

有没有更好的方法可以解决这个问题?

2 个答案:

答案 0 :(得分:1)

如果首先对数据集进行排序,则可以轻松扫描重叠范围。 “无”似乎用于不同地方的不同事物(最小为零),因为它最大“大于任何东西” - 但这比较难。如果你有一个真正的最大值,它会使排序更容易。

(编辑:扫描最大值,因为没有已知的最大值)

MAX = max(val.get('max_width', 0) for val in breakpoints.itervalues()) + 1
# sort by min/max
items = sorted(
    (data['min_width'] or 0, data['max_width'] or MAX, name) 
    for name, data in breakpoints.iteritems())
# check if any range overlaps the next higher item
for i in range(len(items)-1):
    if items[i][0] > items[i][1]:
        print "range is incorrect for", items[i][1]
    elif items[i][1] >= items[i+1][0]:
        print items[i+1][2], 'overlaps'

答案 1 :(得分:0)

你可以从那个带有范围的dict获得:

ranges = { 'small': (None, 640), 'medium': (641, 1024), ...}

然后检查,len(set(ranges.values())) == len(ranges) 编辑:如果要求范围不同,这是有效的。请参阅@ tdelaney关于不相交范围的答案。