Создание коллекции объектов, которые можно получить с помощью тегов - PullRequest
0 голосов
/ 24 мая 2018

Мне нужна коллекция, которая может хранить и извлекать объекты с несколькими, возможно, общими тегами.Мне нужно иметь возможность хранить один объект с несколькими тегами и извлекать все объекты, имеющие один или несколько тегов.

Моя первая идея состояла в том, чтобы коллекция сохраняла массив объектов, а Dictionary<string, Hashset<int>> гдеключ - это тег, а значение - это индексы, к которым применяется тег.

  • Для нескольких тегов получить пересечение коллекций индексов
  • Чтобы удалить тег из объекта, удалите этот индекс из коллекции

однакоЕсли объект удален из коллекции, все индексы после этой точки теперь неверны.

Я двигаюсь в правильном направлении?Есть ли существующая реализация этого, о которой я не знаю, или стандартный подход к коллекциям, который мог бы помочь здесь?

Ответы [ 4 ]

0 голосов
/ 25 мая 2018

Это не лучший способ, но способ, которым я пока пользуюсь, пока не станет проблемой, - это просто коллекция, состоящая из двух словарей;Dictionary<string, Hashset<T>> для получения объектов с тегом и Dictionary<T, Hashset<string>> для получения тегов на объекте.Это просто и функционально, и должно быть достаточно для небольших коллекций.

0 голосов
/ 24 мая 2018

Почему бы не использовать:

Dictionary<List<string>, HashSet<int>> taggedDict = new Dictionary<List<string>, HashSet<int>>();
var searchList = new List<string> { "tag1", "tag4" };
var keys = taggedDict.Keys.Where(x => x.Any(y => searchList.Contains(y)));
0 голосов
/ 24 мая 2018

Вы направились в правильном направлении.Я бы сказал, что вы должны кэшировать общие пересечения в других HashSet<T> экземплярах, чтобы еще больше ускорить и упростить вещи.

однако, если объект удален из коллекции, все индексы после этой точки теперь неверны.

Хотя вы можете создать обратный словарь Dictionary<int, HashSet<string>> вЧтобы удалить данный объект из индекса тега, чтобы избежать итерации всего индекса при удалении какого-либо объекта:

var tags = objectTagMap[394]

foreach(var tag in tags) 
   tagObjectMap[tag].Remove(394)

В любом случае, если вы думаете об индексе в памяти, почему бы вам неиспользовать Redis ?Redis предоставляет вам как хеши (словари), наборы и отсортированные наборы (так и некоторые другие структуры данных).

Это очень очень упрощенный пример того, как вы будете строить ту же стратегию в Redis:

# Store objects as key-value pairs
set object:1 { "id": 1 }
set object:2 { "id": 2 }
set object:3 { "id": 3 }

// sadd (set add) to build the tag index
sadd tagA 1 2
sadd tagB 3

// sunion to get object ids from two or more tags
sunion tagA tagB

// mget (multiple get) to get object data from the result 
// of sunion concatenating "object:" with each object id
// This is a simple example. In a real world system you would use
// SCAN to avoid bottlenecks and being able to leverage paging.
mget object:1 object:2 object:3
0 голосов
/ 24 мая 2018

Дано

public class Something
{
   public HashSet<string> Tags { get; set; }
}

Использование

var list = new List<Something>
               {
                  new Something()
                     {
                        Tags = new HashSet<string>() { "tag1", "tag2" }
                     },
                  new Something()
                     {
                        Tags = new HashSet<string>() { "tag3", "tag4" }
                     }
               };

var searchList = new List<string> { "tag1", "tag4"};

var result = list.Where(x => x.Tags.Any(y => searchList.Contains(y)));

Довольно стандартный подход к памяти

Если вы этого хотелиболее типизированный, используйте перечисления (если они не нужны вам динамически)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...