Какова правильная структура данных для двунаправленного сопоставления «один ко многим»?

#algorithm #data-structures #hash

#алгоритм #структуры данных #хэш

Вопрос:

 user_1 is in [group_1, group_2]
user_2 is in [group_2, group_3]

therefore,

group_1 has members [user_1]
group_2 has members [user_1, user_2]
group_3 has members [user_2]
 

Вариант использования — много чтения, меньше записи, поиск:

  • группы, в которых находится данный пользователь.
  • члены в заданных группах.

Существует ли какая-либо правильная структура данных для этого с низким объемом памяти?

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

1. Разве это не отношение «многие ко многим»?

2. В общем, да. Я говорю, что один ко многим — это выделение вариантов использования.

3. Пропущенные символы подчеркивания:: group_1, group_2, group_3 следует последовательно использовать выше.

4. Спасибо. он пересмотрен.

Ответ №1:

Структура данных Graph может быть лучшим вариантом для решения этой проблемы.

Подход к списку смежности:

Сопоставьте номер группы со списком номеров пользователей, с которыми связаны пользователи.

Карта <Номер группы, список пользователей>

Аналогичный случай с другим отображением.

Сопоставьте номер пользователя со списком номеров групп, с которыми связан этот пользователь.

Карта <Номер пользователя, список групп>

Ответ №2:

Вот некоторый Python, который создает класс из двух сопоставлений и как они используются.

 # Initial input maps users to any iterable collection of groups e.g. a list.
u2g = {'user_1': ['group_1', 'group_2'], 
       'user_2': ['group_2', 'group_3'],
      }

class Bi_map():
    def __init__(self, u2g_in):
        # internal forward map of user to tuple of groups
        self.u2g = {user: tuple(groups)
                    for user, groups in u2g_in.items()}
        # Assemble reverse mapping of group to appendable list of users
        g2u = dict()
        for user, groups in u2g_in.items():
            for group in groups:
                if group in g2u:
                    g2u[group].append(user)
                else:
                    g2u[group] = [user]
        # internal reverse map of group to tuple of users
        self.g2u = {group: tuple(users) 
                    for group, users in g2u.items()}
                    
        
if __name__ == '__main__':
    # Typical use
    bi_map = Bi_map(u2g)
    
    assert bi_map.u2g == {'user_1': ('group_1', 'group_2'), 
                          'user_2': ('group_2', 'group_3')}
    
    assert bi_map.g2u == {'group_1': ('user_1',),
                          'group_2': ('user_1', 'user_2'),
                          'group_3': ('user_2',)}
    
    print(bi_map.u2g['user_2'])     # outputs: ('group_2', 'group_3')
    print(bi_map.g2u['group_2'])    # outputs: ('user_1', 'user_2')
 

Теперь вышесказанное предполагает, что у вас есть начальное одностороннее сопоставление; хотите создать двустороннее сопоставление; затем прочитайте сгенерированные карты с этого момента.

Если вы хотите время от времени добавлять сопоставления nextra, то одной из модификаций было бы сохранение сопоставления строк со списками строк в классе и добавление методов для их обновления.