Ищете способ связать 2 списка обратно вместе в python - PullRequest
0 голосов
/ 08 мая 2020

У меня в основном 1 список: список [(имя 1, оценка 1), (имя 2, оценка 2) и т. Д.]. Я использую оценки из другого списка, чтобы рандомизировать их на основе алгоритма, но после этого я хотел бы связать каждую оценку с каждым именем. Оценки могут быть одинаковыми, но это не важно. Если 2 балла совпадают с разными именами, не имеет значения, какая оценка связана с каким именем, потому что оценка одинакова. Пожалуйста, помогите!

INPUT: list1 = [(0, a), (100, b), (200, c), (300, d)] list2 = [[200, 0], [ 300, 100]]

ОЖИДАЕМЫЙ ВЫХОД: list3 = [[(200, c), (0, a)], [(300, d), (100, b)]]

Как мне получить list3 из list2 и list1?

* list1 = [(0, a), (0, b), (0, c), (0, d)] is также действительный список.

Тогда не имеет значения, если list3 = [[(0, a), (0, b)], [(0, c), (0, d)]] ИЛИ list3 = [ [(0, d), (0, b)], [(0, c), (0, a)]] *

Ответы [ 3 ]

0 голосов
/ 08 мая 2020

Ваш первый список выглядит как справочная таблица. Я думаю, что самый быстрый способ сделать это преобразование - преобразовать list1 в dict, а затем выполнить поиск для преобразования list2 в list3:

dict1 = dict(list1)

list3 = [[(item, dict1[item]) for item in sublist] for sublist in list2]

# output: [[(200, 'c'), (0, 'a')], [(300, 'd'), (100, 'b')]]

Python dicts имеют конструктор, который принимает список пар, просто как ваш list1. Это превращает list1 в таблицу быстрого поиска dict1. Затем вы перебираете свои подсписки, затем перебираете элементы в каждом подсписке и выполняете этот поиск.

Я не помню эффективности конструктора Python dict, но он не хуже O(n log(n)).

Всякий раз, когда у вас есть список пар, иногда стоит подумать, не будет ли проще использовать его как диктант. Python любит dicts.


EDIT: обратите внимание, что dicts может хранить только одно значение на ключ. Первоначально я думал, что это нормально, но было разъяснено, что это не так.

Следующее решение - преобразовать его в мульти-карту, а затем уничтожить его как go. Multimap похожа на dict, но в ней хранится список всех значений, имеющих ключ - это не ограничивается одним значением для каждого ключа. Очевидно, поскольку нам не нужен весь список, нам нужно только одно уникальное значение для каждого экземпляра, мы возьмем последнее значение из списка с карты. Код будет выглядеть очень похоже, но построение мульти-карты будет отличаться от построения dict.

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

from collections import defaultdict

def impose_structure (list1, list2):
    # This multimap will be a map from the key to a list of all values of that key,
    # like {0: ['a', 'b', 'c', 'd']}
    multimap = defaultdict (list)

    for key, value in list1:
        multimap[key].append (value)

    # We'll do the same thing as before, but now we'll remove values from the end
    # so we don't have duplicates
    return [[(item, multimap[item].pop ()) for item in sublist] for sublist in list2]


if __name__ == '__main__':
    list1 = [(0, 'a'), (0, 'b'), (100, 'c'), (100, 'd')]
    list2 = [[100, 0], [0, 100]]

    print (impose_structure (list1, list2))

# outputs: [[(100, 'd'), (0, 'b')], [(0, 'a'), (100, 'c')]]
0 голосов
/ 09 мая 2020

Ваш список1 находится в формате, который может принять словарь, и вы хотите заменить значения их индексированными аналогами такого словаря. Таким образом, самый простой способ - превратить list1 в настоящий словарь и использовать его в понимании списка для сопоставления значений list2:

list1 = [(0, "a"), (100, "b"), (200, "c"), (300, "d")]
list2 = [[200, 0], [300, 100]]

dict1 = dict(list1)    
list3 = [ [(i,dict1[i]) for i in r] for r in list2 ]

print(list3)
[[(200, 'c'), (0, 'a')], [(300, 'd'), (100, 'b')]]
0 голосов
/ 08 мая 2020

Вы можете отсортировать list1 с помощью настраиваемой ключевой функции, хотя это, вероятно, довольно медленно:

def sort_by_order_in_other_list(other_list):
    def _inner(tup):
        return other_list.index(tup[0])
    return _inner

list3 = sorted(list1, key=sort_by_order_in_other_list(list2))

Это может быть оптимальным алгоритмом для очень маленьких списков. Для более длинных списков я бы рекомендовал сделать первый проход, чтобы упростить ссылку на list2:

dict2 = {i: value for i, value in enumerate(list2)}

list3 = sorted(list1, key=lambda x: dict2[x[0]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...