使用python中的数组以更方便的方式编写一个long switch语句

时间:2014-08-02 14:30:15

标签: python arrays list conditional-statements

我已经检查过以下答案: Replacements for switch statement in Python?How to refactor Python "switch statement"

但我认为两者都是指单个案例的简单switch语句。

我遇到的问题是switch语句看起来像这样:

switch(view) {
  case "negatives":
    label = 0;
    break;
  case "cars\\00inclination_000azimuth":
  case "buses\\00inclination_000azimuth":
  case "trucks\\00inclination_000azimuth":
    label = 1;
    break;
  case "cars\\00inclination_045azimuth":
  case "buses\\00inclination_045azimuth":
  case "trucks\\00inclination_045azimuth":
  case "cars\\00inclination_090azimuth":
  case "buses\\00inclination_090azimuth":
  case "trucks\\00inclination_090zimuth":
  case "cars\\00inclination_135azimuth":
  case "buses\\00inclination_135azimuth":
  case "trucks\\00inclination_135azimuth":
    label = 2;
    break;
  # and so on

因此,有很多情况会导致相同的标签。有没有快速的方法来使用列表?我可以在哪里使用这样的东西

a = ["cars\\00inclination_045azimuth","buses\\00inclination_045azimuth","trucks\\00inclination_045azimuth","cars\\00inclination_090azimuth","buses\\00inclination_090azimuth", "trucks\\00inclination_090zimuth","cars\\00inclination_135azimuth","buses\\00inclination_135azimuth","trucks\\00inclination_135azimuth"]

if view in a:
    label = 2

但是,我必须为映射到同一标签的每组案例制作一个列表,然后通过每个案例。

有没有办法执行以下操作,如果没有,那么最简单的方法是什么?

 if view in _any_of_the_lists_i've_made:
     label = the_index_of_that_list

更新

我在问题中显示的值只是少数,以便对问题有一个大概的了解。但我从一些评论中意识到,最好给出我所拥有的全部价值观作为案例。

  • 有3个前缀:"汽车","卡车"和"公共汽车"。
  • 有4个倾斜角度(斜线后的前两个数字)。所以我可以有汽车\ 00inclination_000azimuth,或汽车\ 30inclination_000azimuth或汽车\ 60inclination_000azimuth或汽车\ 90inclination_000azimuth
  • 总共有25种不同的方位角。与45度的差异,所以我可以有汽车\ 00inclination_000azimuth和汽车\ 00inclination_045azimuth一直到汽车\ 00inclination_315azimuth

总的来说,每辆车有25个视图,有3辆车,有75种不同的视图,即75个。

4 个答案:

答案 0 :(得分:3)

您的视图字符串遵循一种模式;它们由<transport>\<inclination>_<azimuth>组成,并且您的标签仅在方位角值上有所不同。

将字符串简化为方位角值,然后使用dict找到您的标签:

labels = {'000': 1, '045': 2, '090': 2, '135': 2}

label = 0 if view == 'negatives' else labels[view.rpartition('_')[-1][:3]]

这会从azimuth字符串中取出 3位数。

为了说明这是如何工作的,一个简短的演示:

>>> "cars\\00inclination_000azimuth".rpartition('_')
('cars\\00inclination', '_', '000azimuth')
>>> "cars\\00inclination_000azimuth".rpartition('_')[-1]
'000azimuth'
>>> "cars\\00inclination_000azimuth".rpartition('_')[-1][:3]
'000'

str.rpartition()分割最后一个_字符,我们从中选择最后一个元素,然后从最后一个元素中分割前3个字符。

如果你也需要改变倾向,那就解析一下:

labels = {
    None: 0,
    ('00', '000'): 1,
    ('00', '045'): 2,
    ('00', '090'): 2,
    ('00', '135'): 2,
    # etc.
}

if view == 'negatives':
    key = None
else:
    key = view.partition('\\')[-1][:2], view.rpartition('_')[-1][:3]
label = labels[key]

通过将视图缩小到只有那些重要的部分,您可以大大减少字典的大小,或者至少您需要输入的部分

当然,直接查看视图字符串会更快。您始终可以生成上述字典中的完整字符串:

for key, label in labels.items():
    if key is None:
        labels['negatives'] = label
        continue
    for vehicle in ('cars', 'trucks', 'buses'):
        labels['{}\\{}inclination_{}azimuth'.format(vehicle, *key)] = label

然后直接查找您的标签:

label = labels[view]

答案 1 :(得分:0)

正如一些评论者指出的那样,您最好的解决方案是更充分地解析字符串,并获取其中的关键信息,这将减少您的案例。如果由于某种原因你不能,你可以这样做:

CASES = [
    {
        "negatives",
    },
    {
        "cars\\00inclination_000azimuth",
        "buses\\00inclination_000azimuth",
        "trucks\\00inclination_000azimuth",
    },
    {
        "cars\\00inclination_045azimuth",
        "buses\\00inclination_045azimuth",
        "trucks\\00inclination_045azimuth",
        "cars\\00inclination_090azimuth",
        "buses\\00inclination_090azimuth",
        "trucks\\00inclination_090zimuth",
        "cars\\00inclination_135azimuth",
        "buses\\00inclination_135azimuth",
        "trucks\\00inclination_135azimuth",
    },
]

def find_label(view):
    for label, views in enumerate(CASES):
        if view in views:
            return label

请注意,我已使用集来加速view in views检查。

更好的是,您可以将您的集合列表预处理为单个字典:

CASE_DICT = { view:label for label, views in enumerate(CASES) for view in views }

def find_label(view):
    return CASE_DICT.get(view, None)

答案 2 :(得分:0)

这里的其他答案都很好,但是基于dict的查找表没有任何问题 - 如果你打算经常访问它,一个更大的dict比预处理字符串更快,以便在每次查找时提取值。

def get_label(val):
    label_map = { 
        "negatives": 0,
        "cars\\00inclination_000azimuth": 1,
        "buses\\00inclination_000azimuth": 1,
        "trucks\\00inclination_000azimuth": 1,
        "cars\\00inclination_045azimuth": 2,
        (...etc...)
    }
    return label_map[val]

答案 3 :(得分:0)

由于车辆的映射存在巨大的重叠:倾角:方位角值,您可以使用intertools product将重叠字符串的元组描述为映射。

假设您可以将label描述为'2',其中车辆为['cars', 'buses', 'trucks']中的任何一个,方位角为['0']中的任意一个且倾角为{{1}中的任意一个你的例子说的是什么。

你可以这样做:

['45', '90', '135']

然后很容易添加添加&#39;案例&#39;使用.update,product和dict comprehension的值(借用C的意义):

from itertools import product
vehicles=['cars', 'buses', 'trucks']

switch={}
switch.update({t:2 for t in product(vehicles, ['0'], ['45', '90', '135'])})
print switch
# {('buses', '0', '90'): 2, ('buses', '0', '45'): 2, ('cars', '0', '135'): 2, ('trucks', '0', '135'): 2, ('trucks', '0', '90'): 2, ('cars', '0', '45'): 2, ('trucks', '0', '45'): 2, ('cars', '0', '90'): 2, ('buses', '0', '135'): 2}

重复每个可描述的车辆组合:倾角:方位角值。

然后,您可以直接从感兴趣的值的元组的键值分配标签:

>>> switch.update({t:1 for t in product(vehicles, ['0'], ['0'])})
>>> switch
{('buses', '0', '90'): 2, ('buses', '0', '45'): 2, ('cars', '0', '135'): 2, ('trucks', '0', '135'): 2, ('trucks', '0', '90'): 2, ('cars', '0', '45'): 2, ('trucks', '0', '45'): 2, ('cars', '0', '90'): 2, ('buses', '0', '135'): 2, ('cars', '0', '0'): 1, ('buses', '0', '0'): 1, ('trucks', '0', '0'): 1}

无需全部输入。

您还可以使用>>> label=switch[('cars', '0', '0')] >>> label 1 来设置默认值:

.get()