我有一个书签列表。每个书签都有一个关键字列表(存储为HashSet)。我还有一组所有可能的关键词(“宇宙”)。
我想找到大多数书签中出现的关键字。
我有1356个书签,总共有698,539个关键字,其中187,358个是唯一的。
如果我遍历Universe中的每个关键字并计算它出现的书签数量,我就会进行254,057,448次检查。我的机器需要35秒。
算法非常简单:
var biggest = universe.MaxBy(kw => bookmarks.Count(bm => bm.Keywords.Contains(kw)));
我不确定是否可以加快速度,但有什么我可以做的吗?也许以某种方式并行化它?
dtb的解决方案需要不到200毫秒来构建宇宙并找到最大的元素。这么简单。
var freq = new FreqDict();
foreach(var bm in bookmarks) {
freq.Add(bm.Keywords);
}
var biggest2 = freq.MaxBy(kvp => kvp.Value);
FreqDict
只是我在Dictionary<string,int>
之上构建的一个小课程。
答案 0 :(得分:4)
您可以获取所有关键字,对其进行分组,并获得最大的群组。这会占用更多内存,但应该更快。
我尝试了这个,在我的测试中它快了大约80倍:
string biggest =
bookmarks
.SelectMany(m => m.Keywords)
.GroupBy(k => k)
.OrderByDescending(g => g.Count())
.First()
.Key;
试运行:
1536 bookmarks
153600 keywords
74245 unique keywords
Original:
12098 ms.
biggest = "18541"
New:
148 ms.
biggest = "18541"
答案 1 :(得分:2)
您无需遍历整个Universe。想法是创建一个查找并跟踪最大值
public Keyword GetMaxKeyword(IEnumerable<Bookmark> bookmarks)
{
int max = 0;
Keyword maxkw = null;
Dictionary<Keyword, int> lookup = new Dictionary<Keyword, int>();
foreach (var item in bookmarks)
{
foreach (var kw in item.Keywords)
{
int val = 1;
if (lookup.ContainsKey(kw))
{
val = ++lookup[kw];
}
else
{
lookup.Add(kw, 1);
}
if (max < val)
{
max = val;
maxkw = kw;
}
}
}
return maxkw;
}
答案 2 :(得分:2)
我没有您的样本数据,也没有进行任何基准测试,但我会采取措施。可以改进的一个问题是大多数bm.Keywords.Contains(kw)
检查都是未命中的,我认为可以避免这些检查。最受限制的是给定书签的任何一个关键字集合(即:它通常比宇宙小得多)所以我们应该从那个方向开始而不是从另一个方向开始。
我正在思考这些问题。内存需求要高得多,因为我没有对任何事情进行基准测试,它可能会更慢,或者没有帮助,但如果它不适合你,我会删除我的答案。
Dictionary<string, int> keywordCounts = new Dictionary<string, int>(universe.Length);
foreach (var keyword in universe)
{
keywordCounts.Add(keyword, 0);
}
foreach (var bookmark in bookmarks)
{
foreach (var keyword in bookmark.Keywords)
{
keywordCounts[keyword] += 1;
}
}
var mostCommonKeyword = keywordCounts.MaxBy(x => x.Value).Key;
答案 3 :(得分:1)
50ms:
>>> import random
>>> universe = set()
>>> bookmarks = []
>>> for i in range(1356):
... bookmark = []
... for j in range(698539//1356):
... key_word = random.randint(1000, 1000000000)
... universe.add(key_word)
... bookmark.append(key_word)
... bookmarks.append(bookmark)
...
>>> key_word_count = {}
>>> for bookmark in bookmarks:
... for key_word in bookmark:
... key_word_count[key_word] = key_word_count.get(key_word, 0) + 1
...
>>> print max(key_word_count, key=key_word_count.__getitem__)
408530590
>>> print key_word_count[408530590]
3
>>>