#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.