我需要一个可以存储和检索具有多个可能共享标记的对象的集合。我需要能够存储一个具有多个标签的对象,并检索具有一个或多个标签的所有对象。
我的第一个想法是集合存储一个对象数组,一个Dictionary<string, Hashset<int>>
,其中键是标记,值是标记适用的索引。
但是,如果从集合中删除了一个对象,那么该点之后的所有索引现在都是不正确的。
我是朝着正确的方向前进吗?是否存在我不知道的现有实现,或者对此有帮助的标准集合方法?
答案 0 :(得分:2)
<强>鉴于强>
<div class="content"></div>
<强>用法强>
public class Something
{
public HashSet<string> Tags { get; set; }
}
内存方法相当标准
如果你想要更多打字,请使用枚举(如果你不需要动态)
答案 1 :(得分:1)
你朝着正确的方向前进。我会说你应该缓存其他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
答案 2 :(得分:0)
为什么不使用:
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)));
答案 3 :(得分:0)
这不是最好的方法,但我现在使用的方式直到它成为一个问题只是一个由两个字典组成的集合; Dictionary<string, Hashset<T>>
获取带有标记的对象,Dictionary<T, Hashset<string>>
获取对象上的标记。它简单实用,应该适合较小的集合。