Объединение списков в Python 3, таких как SQL JOIN - PullRequest
0 голосов
/ 21 января 2019

У меня есть 2 объекта (представьте их как таблицы базы данных):

O1:
field1 (ID)
field2
поле3

O2:
field1
field2
field3 (ID)
field4

У меня есть 2 списка:
L1 - список объектов O1
L2 - список объектов O2

Вопрос: есть ли способ объединить эти два списка с помощью L1.field1 и L2.field3, как SQL JOIN? Количество элементов в двух списках всегда равно (отношение 1: 1), но они не обязательно отсортированы по этим двум полям.

Ответы [ 3 ]

0 голосов
/ 21 января 2019

Вы можете сделать это простым и наивным способом:

joined = [ i + j for i in L1 for j in L2 if i[0] == j[2] ]

Это, безусловно, будет намного эффективнее, чем панды для крошечных списков, но плохо работает для больших.

Aсредним способом было бы использовать вспомогательный словарь:

D2 = { j[2]: j for j in L2 }
joined = [ i + D2[i[0]] for i in L1 ]

Теперь он будет работать на O (len (L1)) + O (len (L2)) вместо O (len (L1)) * O(LEN (L2)).Еще менее эффективен, чем высокооптимизированный модуль pandas для очень больших наборов данных, но гораздо лучше, чем наивный подход для не слишком маленьких списков.

0 голосов
/ 21 января 2019

Я пытаюсь показать пример, если я понял. Допустим, у вас есть эти классы:

class User():
  def __init__(self, id, name):
    self.id = id
    self.name = name

class Image():
  def __init__(self, id, user_id, filename):
    self.id = id
    self.user_id = user_id
    self.filename = filename

И следующие коллекции:

users = [User(1, 'Jim'), User(2, 'Spock')]
images = [Image(1, 1, 'jim_1.jpg'), Image(2, 1, 'jim_2.jpg'), Image(3, 2, 'spk_1.jpg')]

Когда вы выбираете пользователя из коллекции, скажем, первое:

user = users[0]

Вы можете запросить изображения следующим образом:

user_images = [ image for image in images if image.user_id == user.id ]

for image in user_images:
  print(image.filename)

Хотя если у вас есть изображение, так как в этом случае это отношение один ко многим:

image = images[0]
user = [user for user in users if user.id == image.user_id][0] # [0] as it is 1:n relation


Для таблицы соединений:
join_table = [ {'name': user.name, 'filename': image.filename} for user in users for image in images if user.id == image.user_id ]

for e in join_table:
  print(e['name'], e['filename'])

Что возвращает:

# Jim jim_1.jpg
# Jim jim_2.jpg
# Spock spk_1.jpg
0 голосов
/ 21 января 2019

pandas имеет множество функций для работы с данными таким образом.

Превратите свои списки в pd.DataFrame с, и тогда вы можете использовать pd.join. Как и SQL JOIN, это позволяет вам указывать такие параметры, как внутренний, левый, правый, внешний.

dfL1.set_index(field1).join(dfL2.set_index(field3))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...