Почему моя программа на Python не находит разницы между двумя наборами?

#python #set

#python #установить

Вопрос:

Я могу успешно получить все IP-адреса на моем wifi и сохранить их в списке knownIP. Затем я тестирую его, получая доступ к сети Wi-Fi с моего iPhone. Второе сканирование успешно обнаруживает и добавляет новый IP-адрес в список. Я делаю оба списка набором, а затем использую разницу. Но это только печать set() и это пустой набор.

 # print statements are added for troubleshooting purposes
knownIPlist = initial_scan()
print(knownIPlist)
knownIPList_set = set(knownIPlist)
scanWifi = True
while scanWifi:
    print("Turn on iPhone") 
    time.sleep(15)
    print("Scanning...")
    scanIPlist = scan()
    print(scanIPlist)
    scanIPlist_set = set(scanIPlist)
    newIPlist = knownIPList_set.difference(scanIPlist_set)
    print(newIPlist)
    # for newIP in newIPlist:
    #    print(newIP)
    print("waiting...")
 

Вывод:

 '192.168.1.64', '192.168.1.77', '192.168.1.190', '192.168.1.208', '192.168.1.216', '192.168.1.217', '192.168.1.220', '192.168.1.222', '192.168.1.227', '192.168.1.254', '192.168.1.66'

Turn on iPhone

Scanning...
'192.168.1.64', '192.168.1.77', '192.168.1.190', '192.168.1.208', '192.168.1.210', '192.168.1.216', '192.168.1.217', '192.168.1.220', '192.168.1.222', '192.168.1.227', '192.168.1.254', '192.168.1.66'

set()

waiting...
 

Он успешно находит новый IP-адрес (.210) при новом сканировании, но просто выводит «set ()». Это просто пустой набор. Почему он не добавляет и не печатает новый IP-адрес .210 в newIPlist?

Ответ №1:

set.difference возвращает элементы в левой руке set , которых нет в правой руке set . Добавление элементов в правый набор может только уменьшить количество элементов в результате, а не добавить к нему. Как написано, вы будете сообщать об IP-адресах, которые исчезли с момента создания оригинала set , а не о новых IP-адресах, которые появились с тех пор.

Чтобы сообщать только о новых IP-адресах, отмените вызов:

 newIPlist = scanIPlist_set.difference(knownIPList_set)
 

Или для краткости (и чтобы было понятнее, что вы удаляете элементы из одного, где именованный difference метод менее понятен и, вероятно, является источником вашей путаницы):

 newIPlist = scanIPlist_set - knownIPList_set
 

Комментарии:

1. Спасибо за быстрый ответ! Я попробовал это перед публикацией, и это не сработало. Другой комментатор ниже сказал, чтобы посмотреть, сделал ли я == и напечатал True, и он действительно напечатал true, несмотря на наличие еще одного IP-адреса? Есть идеи, почему это может быть?

2. @BrandonJacobson: это определенно не будет вести себя так с описанным вами результатом; 192.168.1.210 находится в одном, но не в другом. Итак, вы что-то опускаете, и / или поведение, которое вы описываете, невозможно воспроизвести, потому что IP-адреса не совпадают в вашем текущем запуске. Учитывая, что вы сканируете IP-адреса в сети, повторный запуск того же сценария после установки нового IP-адреса не приведет к различию; вы уверены, что IP-адрес отсутствует в начале и появляется позже? Я предполагаю, что при вашем втором запуске iPhone уже был назначен IP-адрес с самого начала.

3. Что type(scanIPList) возвращает? Держу пари, что на самом деле это не список, а какой-то генератор. Затем print(scanIPList) использует генератор, поэтому set(ScanIPList) создает пустой набор.

Ответ №2:

knownIPList_set.difference(scanIPlist_set) возвращает все элементы knownIPList_set , которых нет scanIPlist_set . .210 IP scanIPlist_set включен, но нет knownIPList_set . Итак, вам нужно отменить операцию:

 newIPlist = scanIPlist_set.difference(knownIPList_set)
 

Комментарии:

1. Спасибо за быстрый ответ и изменение редактирования! Я не знал, что вывод должен быть в блоке кода. Я попытался изменить порядок перед публикацией, и это не сработало. Другой комментатор ниже сказал, чтобы посмотреть, сделал ли я == и напечатал True, и он действительно напечатал true, несмотря на наличие еще одного IP-адреса? Есть идеи, почему это может быть?

Ответ №3:

Оба набора содержат одинаковые элементы, поэтому, когда вы берете разницу, это приведет к пустому набору, и, следовательно, он печатает set() .

Попробуйте распечатать,

 if(knownIPList_set == scanIPlist_set):
    print("True")
 

Комментарии:

1. Итак, я сделал это, и это действительно напечатало true. Как это возможно? В списке knownIP есть 9 IP-адресов, а затем 10 IP-адресов в scanIPlist, но это все еще верно?

2. Откуда вы взяли, что у них одинаковые элементы? 192.168.1.210 находится в последнем выводе, но не в первом.

3. Вот почему я в замешательстве, но он был прав, что он по-прежнему печатает true .

4. Комментарий выше заставил меня понять, что что-то не так с knownIPlist_set . Когда я распечатываю это, это выглядит так: {‘4’, ‘2’, ‘9’, «‘», ‘0’, ‘5’, ‘1’, ‘.’, ‘8’, ‘6’, ‘7’, ‘,’,’ ‘} Мне нужно будет устранить неполадки с наборами.

Ответ №4:

@Brandon

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

 knownIPList_set = {'192.168.1.64', '192.168.1.77', '192.168.1.190', '192.168.1.208', '192.168.1.216', '192.168.1.217', '192.168.1.220', '192.168.1.222', '192.168.1.227', '192.168.1.254', '192.168.1.66'}
scanIPlist_set = {'192.168.1.64', '192.168.1.77', '192.168.1.190', '192.168.1.208', '192.168.1.210', '192.168.1.216', '192.168.1.217', '192.168.1.220', '192.168.1.222', '192.168.1.227', '192.168.1.254', '192.168.1.66'}

newIPlist_incorrect = knownIPList_set.difference(scanIPlist_set)
print(newIPlist_incorrect)


newIPlist_correct = scanIPlist_set.difference(knownIPList_set)
print(newIPlist_correct)
 

Результат будет следующим:

 set()
{'192.168.1.210'}
 

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

Комментарии:

1. Когда я запускаю этот код в отдельном файле, он работает отлично. Как вы думаете, что-то не так со структурой списков, которые я помещаю в наборы?

2. ваш код правильный, @BrandonJacobson . Просто измените одну строку кода. newIPlist = knownIPList_set.difference(scanIPlist_set) К newIPlist = scanIPlist_set.difference(knownIPList_set)

3. Нет, что-то не так. Ваше предложение натолкнуло меня на идею распечатать фактический knownIPList_set, и он выводит это: {‘4’, ‘2’, ‘9’, «‘», ‘0’, ‘5’, ‘1’, ‘.’, ‘8’, ‘6’, ‘7’, ‘,’, ‘ ‘} Мне придется разобраться, что не так со списками. Спасибо, что подали мне эту идею.

4. здорово, что вы выяснили основную причину. Добро пожаловать!!

5. Есть идеи, почему преобразование списка в набор все портит?

Ответ №5:

Большое вам спасибо за все ваши рекомендации.

Проблема была в коде до моих вопросов. knownIPlist и scanIPlist были строками типов, поэтому, когда я объявлял их как наборы, это выдавало этот результат:

 {'4', '2', '9', "'", '0', '5', '1', '.', '8', '6', '7', ',', ' '}
 

вместо IP-адресов, поэтому сравнение их ничего не делало. Кроме того, это был правильный порядок для получения вывода моего iPhone, подключенного к моему Wi-Fi.

 newIPlist = scanIPlist_set.difference(knownIPList_set)