соответствие в списке из набора значений

1

Я использую 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 не совпадает на обоих входах

  • 0
    Каков ожидаемый результат? Мне неясно, что вы подразумеваете под "поиском по значениям, но он должен совпадать для обеих записей в списке1".
  • 0
    Я хотел бы, чтобы он выводил только GI2 / 1/1 и GI2 / 1/2, потому что GI2 / 1/3 не совпадает на обоих
Показать ещё 3 комментария
Теги:
python-2.7

6 ответов

0
Лучший ответ

Вы можете создать новый 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]

Если у нас есть только список списков и мы хотим, чтобы логические выражения видели, соответствует ли подсписок тому, что мы ищем, то вышеописанное решение может быть возможным.

  • 0
    Ничего себе, именно то, что я искал, можно было бы выполнить одно и то же, если бы они были списками, а один из них не был словарем. Так что, если мне не нужно было получать имя, которое мне просто нужно было передать в списки и посмотреть, совпадают ли они или нет, как бы я изменил код для чего-то подобного?
  • 0
    Вы имеете в виду , если оба list1 и my_dict фактически list S? Так что my_dict или, точнее, my_list - это список списков?
Показать ещё 9 комментариев
0

Вот еще один ответ на ваш вопрос. Спасибо за размещение вопроса, потому что это будет полезно для меня в будущем, когда мне придется играть с устройствами 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']
0

Это я считаю, что это соответствует вашим требованиям. Это не однострочник, как ранее представили другие, однако он обеспечивает правильное решение наряду с удобочитаемостью. Очень чистое решение.

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
0

Не уверен, что я понял, что вы хотите, но что-то вроде?

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

(и просто удалите разрыв, если вы хотите перечислить все записи, соответствующие вашим ограничениям)

0

Вы можете просто использовать 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

Я думаю, что оба эти метода довольно понятны: вы знаете, что они делают, просто глядя на них

Я надеюсь, это поможет вам!

-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'])
  • 0
    Я думаю, что это довольно нечитаемо и неэффективно

Ещё вопросы

Сообщество Overcoder
Наверх
Меню