Сопоставление значений словаря со словарем

#python #dictionary

#python #словарь

Вопрос:

Я ищу совпадения между цитатами CoinBuy и CoinSell.

Я смог подсчитать экземпляры, и когда один или несколько из них появляются 6 раз, я знаю, что у меня есть совпадение по всем 6 параметрам. И это здорово.

Но когда я изо всех сил пытаюсь соединить ‘CoinBuy’ с ‘coinsell’s

 all_options = [
    {'CoinBuy': 1, 'Base': 'DEXE', 'Quote': {'USDT', 'ETH', 'BUSD'}}, 
    {'CoinBuy': 2, 'Base': 'BOND', 'Quote': {'USDT', 'BTC', 'BUSD'}}, 
    {'CoinBuy': 3, 'Base': 'STX', 'Quote': {'USDT', 'BTC', 'BUSD'}}, 
    {'CoinSell': 1, 'Base': 'NAS', 'Quote': {'ETH', 'BTC'}}, 
    {'CoinSell': 2, 'Base': 'CHESS', 'Quote': {'USDT', 'BTC', 'BUSD'}}, 
    {'CoinSell': 3, 'Base': 'REP', 'Quote': {'USDT', 'ETH', 'BTC', 'BUSD'}}
]
 

Ожидаемый результат:

 Matches
CoinBuy 1 amp; CoinSell 3  in common 'ETH'

CoinBuy 2 amp; CoinSell 2  in common 'USDT', 'BTC', 'BUSD'
CoinBuy 3 amp; CoinSell 1  in common 'BTC', 'BUSD'
 

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

1. Вы ищете совпадения только между определенными парами? Например, вас волнует, что CoinBuy 1 и CoinSell 2 -> USDT, BUSD?

2. Вы можете использовать set intersection для поиска общих элементов в Quote .

3. нет, они могут совпадать с любой комбинацией

4. Тогда почему этой пары нет в вашем ожидаемом выводе?

5. Составьте список всех покупок, другой список всех продаж. Затем используйте вложенный цикл для сравнения каждой покупки с каждой продажей. Если есть какие-либо общие кавычки, выведите совпадение.

Ответ №1:

Это вполне возможно:

 dx = dict()
for opt in all_options:
    for quote in opt.get('Quote'):
        ls = dx.get(quote, [])
        ls.append(opt)
        dx[quote] = ls

commonalities = {}

for exchange, opts in dx.items():
    for i in range(len(opts)):
        left = opts[i]
        for j in range(i 1,len(opts)):
            right = opts[j]
            buy_index = sell_index = None
            if 'CoinBuy' in left and 'CoinSell' in right:
                buy_index = left.get('CoinBuy')
                sell_index = right.get('CoinSell')
            elif 'CoinBuy' in right and 'CoinSell' in left:
                buy_index = right.get('CoinBuy')
                sell_index = left.get('CoinSell')
            # Both other cases are invalid pairs
            if buy_index and sell_index:
                commonality = commonalities.get((buy_index, sell_index), [])
                commonality.append(exchange)
                commonalities[(buy_index, sell_index)] = commonality
                
for commonality, exchanges in commonalities.items():
    buy_index, sell_index = commonality
    excs = ", ".join((f"'{e}'" for e in exchanges))
    print(f"CoinBuy {buy_index} amp; CoinSell {sell_index}  in common {excs}")
 

Тем не менее, вышесказанное довольно неудобно и довольно грубо. Основной алгоритм:

  • Переверните структуру данных, чтобы создать словарь, который использует exchange в качестве ключа, а ваши параметры — в качестве значений. Таким образом, вы знаете для каждого обмена, какие параметры относятся.
  • Для каждого обмена мучительно создавайте пары между вариантами, если каждая сторона пары имеет противоположные типы (покупка против продажи).
  • Переверните индексацию еще раз, выведя индексы сопряжения в качестве ключа и добавив к каждому обмену тот же ключ.
  • Просмотрите список индексов сопряжения и распечатайте все совпадающие обмены.

Вывод выглядит следующим образом:

 >>> for commonality, exchanges in commonalities.items():
...     buy_index, sell_index = commonality
...     excs = ", ".join((f"'{e}'" for e in exchanges))
...     print(f"CoinBuy {buy_index} amp; CoinSell {sell_index}  in common {excs}")
... 
CoinBuy 1 amp; CoinSell 2  in common 'USDT', 'BUSD'
CoinBuy 1 amp; CoinSell 3  in common 'USDT', 'BUSD', 'ETH'
CoinBuy 2 amp; CoinSell 2  in common 'USDT', 'BUSD', 'BTC'
CoinBuy 2 amp; CoinSell 3  in common 'USDT', 'BUSD', 'BTC'
CoinBuy 3 amp; CoinSell 2  in common 'USDT', 'BUSD', 'BTC'
CoinBuy 3 amp; CoinSell 3  in common 'USDT', 'BUSD', 'BTC'
CoinBuy 1 amp; CoinSell 1  in common 'ETH'
CoinBuy 2 amp; CoinSell 1  in common 'BTC'
CoinBuy 3 amp; CoinSell 1  in common 'BTC'
 

Единственная причина, по которой я изложил это, а не (более уместно) позволил вам сначала попробовать, заключается в том, что интуиция для изменения индексации не является обычной, но она может значительно упростить такую обработку. Кроме того, это демонстрирует, насколько неудобна ваша исходная структура данных (почему ключи ‘CoinBuy’ и ‘CoinSell’, а не значения другого ключа, скажем, ‘transaction_type’?) и сколько дополнительной логики это в конечном итоге заставляет вас.

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