2015-09-09 2 views
1

Что было бы лучшим способом сделать следующий шаблон?Как уменьшить повторяющийся код в инструкции if/elif

for platform_id in previous_platform_ids: 
    if self.series.get(platform_id): 
     del self.series[platform_id] 
    elif self.seasons.get(platform_id): 
     del self.seasons[platform_id] 
    elif self.episodes.get(platform_id): 
     del self.episodes[platform_id] 
    elif self.movies.get(platform_id): 
     del self.movies[platform_id] 
    elif self.bundles.get(platform_id): 
     del self.bundles[platform_id] 

В принципе, я хочу перебирать кучу идентификаторов и удалять этот идентификатор из списка, который содержит его.

+0

'.get' не существует для списка. Вы имеете в виду что-то вроде 'try: del x [x.index (element)]; кроме ValueError: pass'? – jojonas

+1

@jojonas они должны быть словарями, через контекст вы можете сказать, что они должны быть словарями –

+1

Вы хотите удалить идентификатор только из первого списка, в котором он находится? –

ответ

2

Один из способов сделать это, чтобы перебирать каждый content_type и использовать метод getattr, чтобы проверить, если он есть:

content_types = ['series', 'seasons', 'episodes', 'movies', 'bundles'] 
for url in previous_urls: 
    for content_type in content_types: 
     if getattr(self, content_type).get(url): 
      del getattr(self, content_type)[url] 
      break 
+0

Мне нравится этот ответ :) –

+1

Звонок 'getattr' посторонний; вы можете выполнять итерацию непосредственно над '[self.series, self.seasons, self.episodes, self.movies, self.bundles]'. – chepner

+1

вы можете добавить 'break' внутри' if' .... –

2
self.series.pop(platform_id,None) 
self.seasons.pop(platform_id,None) 
self.episodes.pop(platform_id,None) 
self.movies.pop(platform_id,None) 
self.bundles.pop(platform_id,None) 

кажется, что он будет делать то же самое (или на самом деле не совсем это приведет к удалению его из всех словарей (ключ) присутствует в не только, первом он находит, что ваш код будет удалить только первый экземпляр находит ... не уверен, если это является намеренным)

грубых вы могли бы сделать что-то вроде

for content_type in content_types: 
    getattr(self, content_type).pop(platform_id,None) 

если вы только хотели, чтобы удалить первые вы нашли вы могли бы сделать

content_dicts = [self.series,self.seasons,self.episodes,self.movies,self.bundles] 
next(x.pop(platform_id,None) for x in content_dicts if platform_id in x) 
+1

Я что-то упустил? Какая структура данных имеет этот метод '.pop (..., ...)'? Я попробовал список в Python 2 и Python 3.4, но 'pop() занимает не более 1 аргумента (2 заданного)'. – jojonas

+0

словари ... –

+1

это не то же самое, что показано OP, вы можете удалить 5 элементов, а только в исходном коде удаляется по одному за раз –

2

насчет:

dicts = [self.series, ..., ] 
remove_id_func = lambda _id: map(lambda dct: dct.pop(_id, None), dicts) 

Как-то держать их в списке кажется более привлекательным, и теперь используют его следующим образом:

remove_id_func(some_id) 

Канун п лучше то, чтобы держать их в отображении:

dicts = { 
    "series": self.series, 
    "movies": self.movies, 
    ... 
} 

И функция удалить теперь становится:

remove_id_func = lambda _id: map(lambda kv: kv[1].pop(_id, None), dicts.items()) 

Вы можете использовать методы класса с простыми петлями, которые, вероятно, лучше, чем эти остроты, которые являются недостижимыми.

Обратите внимание, что эти операции удаляют элемент из всех списков, чего вы, вероятно, хотите.

+1

Я согласен, что лучше держать их в списке ... я думаю, что дикт, вероятно, (хотя вы правы, это улучшение по сравнению с списком) ... +1 –

+0

Понимание списка '[dct.pop (_id, None) для dct in dicts]' вместо 'map' будет еще приятнее. – chepner