Python проверяет равенство кортежей

#python #tuples

#python #Кортежи

Вопрос:

У меня есть числовой массив IP-адресов источника и назначения

 consarray
array([['10.125.255.133', '104.244.42.130'],
   ['104.244.42.130', '10.125.255.133']], dtype=object)
  

Фактический массив намного больше этого.

Я хочу создать набор уникальных пар соединений из массива:

В данном примере: ясно, что обе строки массива numpy являются частью одного и того же соединения (просто src и destination меняются местами, поэтому они являются исходящими и входящими соответственно).

Я попытался создать набор уникальных кортежей. вот так:

 conset = set(map(tuple,consarray))
conset
{('10.125.255.133', '104.244.42.130'), ('104.244.42.130', '10.125.255.133')}
  

На самом деле я хочу, чтобы (‘10.125.255.133’, ‘104.244.42.130’) и (‘104.244.42.130’, ‘10.125.255.133’) считались одинаковыми, чтобы в наборе был только один из них.

Может кто-нибудь сказать мне, как мне это сделать?

Редактировать:

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

Я хочу, чтобы первое вхождение всегда сохранялось независимо от IP-адреса.

В приведенном выше примере: (‘10.125.255.133’, ‘104.244.42.130’) появляется первым, так что это исходящее соединение, я хочу сохранить это.

Если приведенный выше пример изменился на:

 consarray
array(['104.244.42.130', '10.125.255.133']],
    [['10.125.255.133', '104.244.42.130'],dtype=object)
  

Я бы хотел, чтобы (‘104.244.42.130’, ‘10.125.255.133’) были сохранены.

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

1. Делает set(frozenset(el) for el in consarray) ли то, что вы хотите?

2. @JonClements Гений! Спасибо. всегда ли это гарантирует, что первый сохраняется, а второй игнорируется?

3. Я не верю, что это произойдет…

4. Порядок @VikashB в set (или frozenset, если на то пошло) не гарантируется.

5. @JonClements Маловероятный побочный эффект использования frozenset будет в случае, когда оба IP-адреса идентичны (надеюсь, невозможно), оставляя вам frozenset всего из 1 элемента. Позже, если вы попытаетесь получить «два» члена набора, это будет выглядеть не совсем так, как вы ожидаете

Ответ №1:

Вы можете либо применить сортировку перед созданием кортежей:

 conset = set(map(lambda x: tuple(sorted(x)), consarray))
  

Или используйте fronzensets вместо кортежей:

 conset = set(map(frozenset, consarray))
  

Чтобы гарантировать, что первый элемент будет сохранен, а второй не вставлен, вы можете использовать обычный for цикл:

 conset = set()
for x in consarray:
    x = frozenset(x) 
    if x in conset:
        continue
    conset.add(x)
  

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

1. Хорошо, можете ли вы объяснить, как работает подход frozenset, я заглянул в документы, и это неясно, можете ли вы также указать, какой из них будет удален, так ли это, что первый всегда будет сохранен?

2. frozensets — это варианты набора , которые являются неизменяемыми и хешируемыми. Набор не может быть вложен в другой набор, поэтому вместо этого вы будете использовать frozenset .

Ответ №2:

Сначала вы можете отсортировать их:

 conset = set(map(tuple, map(sorted, consarray)))
print (conset)
  

дает:

 {('10.125.255.133', '104.244.42.130')}
  

Ответ №3:

Поскольку вы используете numpy , вы можете использовать numpy.unique , например:

 a = np.array([('10.125.255.133', '104.244.42.130'), ('104.244.42.130', ' 10.125.255.133')])
  

Затем np.unique(a) дает вам:

 array(['10.125.255.133', '104.244.42.130'], dtype='<U14')
  

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

1. Ну, я отредактировал вопрос, но это решение, похоже, гарантирует, что кортеж, в котором первым указан меньший IP-адрес, будет сохранен, я на самом деле хочу, чтобы первый кортеж сохранялся независимо от ip.