Я использую Python 2.7, и у меня есть следующий список:
list1 = ['switchport port-security maximum', 'switchport port-security aging']
И тогда у меня есть словарь, как это:
my_dict = {}
my_dict["GI2/1/1"] = [
'switchport port-security maximum 10',
'switchport port-security maximum 3 vlan access',
'switchport port-security maximum 1 vlan voice',
'switchport port-security aging time 25',
'switchport port-security aging type inactivity',
'switchport port-security'
]
my_dict["GI2/1/2"] = [
'switchport port-security maximum 5',
'switchport port-security maximum 5 vlan access',
'switchport port-security maximum 3 vlan voice',
'switchport port-security aging time 20',
'switchport port-security aging type inactivity',
'switchport port-security'
]
my_dict["GI2/1/3"] = [
'switchport port-security maximum 10',
'switchport port-security maximum 3 vlan access',
'switchport port-security maximum 1 vlan voice',
'switchport port-security'
]
Я пытаюсь найти способ, которым я могу искать значения, но он должен соответствовать обеим записям в list1
У меня есть следующий код, но он будет соответствовать одному, а затем вспыхнет, я знаю, почему он вспыхивает, но я не могу найти способ заставить его совпадать на обеих записях, а затем всплыть. Я знаю, что могу использовать all(), чтобы точно соответствовать всем, но я просто смотрю, существуют ли обе эти записи.
for name, val in my_dict.iteritems():
for v in val:
for i in list1:
if i in v:
print name
break
Цель состоит в том, чтобы вывести только GI2/1/1 и GI2/1/2, потому что GI2/1/3 не совпадает на обоих входах
Вы можете создать новый dict
который фиксирует результаты.
result = {key: set([item for item in list1 for things in val if item in things]) for key, val in my_dict.iteritems()}
#{'GI2/1/1': {'switchport port-security maximum', 'switchport port-security aging'}, 'GI2/1/2': {'switchport port-security maximum', 'switchport port-security aging'}, 'GI2/1/3': {'switchport port-security maximum'}}
result = [key for key, val in result.iteritems() if val == set(list1)]
#['GI2/1/1', 'GI2/1/2']
Это определенно можно сделать в одну строку, но я подумал, что будет проще увидеть, что происходит с двумя шагами. Я храню все совпадения в списке, который превращается в set
(удаляет дубликаты), который затем сравнивается с желаемыми совпадениями в list1
.
РЕДАКТИРОВАТЬ: Как @blhsing указал, set
в Python неупорядочен. Вместо того, чтобы составлять list
из моих значений в result
, я делаю set
из list1
так как я не думаю, что у OP будут дубликаты в list1
.
Другой способ - использовать all
и проверять все элементы.
result = {key: set([item for item in list1 for things in val if item in things]) for key, val in my_dict.iteritems()}
result = [key for key, val in result.iteritems() if all([config in val for config in list1])]
# ['GI2/1/1', 'GI2/1/2']
РЕДАКТИРОВАНИЕ № 2: Из-за запроса OP в комментариях. Вот еще один потенциальный путь. (По мотивам @Josué Cortina ответ ниже).
my_list = [[
'switchport port-security maximum 10',
'switchport port-security maximum 3 vlan access',
'switchport port-security maximum 1 vlan voice',
'switchport port-security aging time 25',
'switchport port-security aging type inactivity',
'switchport port-security'
], [
'switchport port-security maximum 5',
'switchport port-security maximum 5 vlan access',
'switchport port-security maximum 3 vlan voice',
'switchport port-security aging time 20',
'switchport port-security aging type inactivity',
'switchport port-security'
], [
'switchport port-security maximum 10',
'switchport port-security maximum 3 vlan access',
'switchport port-security maximum 1 vlan voice',
'switchport port-security'
]]
result = []
for sub_list in my_list:
if all([True if any([config in item for item in sub_list]) else False for config in list1]):
result.append(True)
else:
result.append(False)
#[True, True, False]
Если у нас есть только список списков и мы хотим, чтобы логические выражения видели, соответствует ли подсписок тому, что мы ищем, то вышеописанное решение может быть возможным.
list1
и my_dict
фактически list
S? Так что my_dict
или, точнее, my_list
- это список списков?
Вот еще один ответ на ваш вопрос. Спасибо за размещение вопроса, потому что это будет полезно для меня в будущем, когда мне придется играть с устройствами Cisco.
# list of cisco switch features
enabled_features = ['switchport port-security maximum', 'switchport port-security aging']
# dictionary used to store the
# cisco switch configuration
cisco_interface_configs = {}
cisco_interface_configs["GI2/1/1"] = [
'switchport port-security maximum 10',
'switchport port-security maximum 3 vlan access',
'switchport port-security maximum 1 vlan voice',
'switchport port-security aging time 25',
'switchport port-security aging type inactivity',
'switchport port-security'
]
cisco_interface_configs["GI2/1/2"] = [
'switchport port-security maximum 5',
'switchport port-security maximum 5 vlan access',
'switchport port-security maximum 3 vlan voice',
'switchport port-security aging time 20',
'switchport port-security aging type inactivity',
'switchport port-security'
]
cisco_interface_configs["GI2/1/3"] = [
'switchport port-security maximum 10',
'switchport port-security maximum 3 vlan access',
'switchport port-security maximum 1 vlan voice',
'switchport port-security'
]
# The regex patterns based on the elements in the list enabled_features
regex_patterns = [re.compile(item) for item in enabled_features]
# iterate of the items contained in the dictionary cisco_interface_configs
for interface_name, interface_value in cisco_interface_configs.items():
# Returns data elements if all of the items are available
if all(any(regex_pattern.match(value) for value in interface_value) for regex_pattern in regex_patterns):
print (interface_name)
print (interface_value)
ВЫХОД
GI2/1/1
['switchport port-security maximum 10', 'switchport port-security maximum 3 vlan access', 'switchport port-security maximum 1 vlan voice', 'switchport port-security aging time 25', 'switchport port-security aging type inactivity', 'switchport port-security']
GI2/1/2
['switchport port-security maximum 5', 'switchport port-security maximum 5 vlan
access', 'switchport port-security maximum 3 vlan voice', 'switchport port-security aging time 20', 'switchport port-security aging type inactivity', 'switchport port-security']
Это я считаю, что это соответствует вашим требованиям. Это не однострочник, как ранее представили другие, однако он обеспечивает правильное решение наряду с удобочитаемостью. Очень чистое решение.
for ky in my_dict.keys():
for i in range(len(list1)):
for val in my_dict[ky]:
if list1[i] in val:
if list1[i] == list1[1]:
print 'match: ', ky
break
выход:
match: GI2/1/1
match: GI2/1/2
Не уверен, что я понял, что вы хотите, но что-то вроде?
def cont(l,s):
for i in l:
if s in i:
return True
return False
for name, val in my_dict.iteritems():
happy=True
for i in list1:
if not cont(val,i):
happy=False
if happy:
print name
break
(и просто удалите разрыв, если вы хотите перечислить все записи, соответствующие вашим ограничениям)
Вы можете просто использовать str.startswith
(если вы не заботитесь позицию вы можете придерживаться использования in
) и объединить его с all
и any
:
for name, val in my_dict.iteritems():
if all(any(v.startswith(l) for v in val) for l in list1):
print name
Вы можете использовать регулярные выражения, хотя это может быть излишним:
import re
regexps = [re.compile(i) for i in list1]
for name, val in my_dict.iteritems():
if all(any(regexp.match(v) for v in val) for regexp in regexps):
print name
GI2/1/1
GI2/1/2
Я думаю, что оба эти метода довольно понятны: вы знаете, что они делают, просто глядя на них
Я надеюсь, это поможет вам!
Вы можете перебирать list1
генерировать наборы ключей в my_dict
, где любые из подсписков строк содержат указанное ключевое слово в list1
, а затем с помощью reduce
функции для получения желаемых результатов через множество пересечения:
reduce(set.intersection, ({n for n, l in my_dict.iteritems() if any(k in i for i in l)} for k in list1))
Это возвращает:
set(['GI2/1/1', 'GI2/1/2'])