Как изменить повторяющееся значение в многомерном массиве

У меня есть словарь (многомерный?), как это:

d = { 0: [3, 5], 1: [5, 7], 2: [4, 7], 3: [4, 3] }

Я хотел бы найти любое повторяющееся значение совпадающей позиции (0) или (1) в списках словарей, и если есть дубликат, то изменить вторую совпадающую пару чисел.

Словарь станет:

{ 0: [3, 5], 1: [5, 7], 2: [7, 4], 3: [4, 3] }

Только позиция (0) будет дубликатом позиции (0), и только позиция (1) будет дубликатом позиции (1), если это имеет смысл. В серии может быть только один дубликат, и все числа должны быть связаны вместе после процесса дедупликации/переворачивания. Ниже показано:

[0 , 1] [1 , 2] [2 , 3] [3 , 0]

Я пытаюсь сопоставить все соседние позиции (1) с позицией (0), поэтому значения, по сути, проходят полный круг (представьте, что это серия линий, которые соединяются от одного конца к другому). Я готов использовать что-нибудь вроде numpy и т. д., что может помочь эффективно решить эту проблему. Вот еще один пример:

{ 'foo': [2, 9], 'bar': [3, 2], 'baz': [3, 9] } 

Что должно получиться:

[2, 9], [9, 3], [3, 2]

Я пробовал кучу вещей, таких как:

l = list(sorted(d.values()))

for i in range(0, len(l)):
    # now what the heck?

Должен ли результат быть диктофоном с исходными ключами, как в вашем первом примере, или упорядоченным списком связанных ребер, как во втором примере?

John Zwinck 07.04.2019 09:33

@JohnZwinck: Привет, Джон, это должен быть упорядоченный список связанных ребер. Индексы словаря на самом деле не имеют большого значения, так как я буду упорядочивать окончательный результат по краям. Спасибо!

Ned Schneebly 07.04.2019 11:35
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
5
2
69
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если вы совершенно не заботитесь о ключе и гарантируете, что парные значения сделают полный круг. Я думаю, вы можете попробовать это:

Сохраните двух соседей каждого числа с помощью dict (улучшите производительность запросов) и начните с любого числа, затем пройдите через цепочку кругов, пока оно снова не достигнет себя.

def reverse_pairs(input_dict):
    pair_values = list(input_dict.values())
    neighbors = defaultdict(list)

    for num1, num2 in pair_values:
        neighbors[num1].append(num2)
        neighbors[num2].append(num1)

    res = [pair_values[0]]
    while res[0][0] != res[-1][1]:
        a1, b1 = res[-1]
        a2, b2 = neighbors[b1]
        res.append([b1, a2 if a1 != a2 else b2])

    return res

прецедент:

def test():
    dict1 = {0: [3, 5], 1: [5, 7], 2: [7, 4], 3: [4, 3]}
    print(reverse_pairs(dict1))

    dict2 = {'foo': [2, 9], 'bar': [3, 2], 'baz': [3, 9]}
    print(reverse_pairs(dict2))

выход:

[[3, 5], [5, 7], [7, 4], [4, 3]]
[[2, 9], [9, 3], [3, 2]]

Надеюсь, это поможет вам, и прокомментируйте, если у вас есть дополнительные вопросы. :)

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

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

Это решение работает на месте, что может быть преимуществом, а может и не быть. Было бы легко преобразовать его в тот, который возвращает исправленный список. У него также есть то преимущество, что он проходит по списку пар только один раз - в худшем случае. В большинстве случаев он может остановиться до конца. Это примерно в семь раз быстрее, чем решение от разведка в моем тестировании.

def fix_chain(pair_dict):
    first_to_pair = dict()
    this, that = None, None # candidates
    for pair in pair_dict.values():
        if pair[0] in first_to_pair: # found the collision
            this = pair
            that = first_to_pair[pair[0]]
        else:
            first_to_pair[pair[0]] = pair
        if this and this[1] in first_to_pair: # this is not reversed...
            that.reverse() # ... so that must be
            return
        if that and that[1] in first_to_pair: # that is not reversed...
            this.reverse() # ... so this must be
            return

Спасибо, что нашли время ответить на мой вопрос. Дома проверю и отпишусь о результатах. Что делает его примерно в семь раз быстрее, чем другой ответ? Мне очень любопытно.

Ned Schneebly 08.04.2019 05:51

Хороший вопрос! Я не профилировал другой ответ. Однако я должен отметить, что я тестировал списки от десяти тысяч до миллионов пар. Со списком из 10000 пар функции занимают 1 миллисекунду и 7 миллисекунд соответственно. Наверное, не имеет большого практического значения :)

Nathan Vērzemnieks 08.04.2019 06:18

Другие вопросы по теме