我有一个articles
列表,每个列表都有一个简单的字符串数组Tags
。我像这样计算标签频率:
计算标记频率
getTags = (articles) ->
tags= {}
for article in articles
for tag in article.Tags
tags[tag] = (tags[tag] or 0) + 1
tags
示例结果
生成的tags
地图是一个对象,其属性名称设置为Tag
名称,属性值设置为频率计数,如下所示:
问题
我想通过属性值(频率计数)来订购此列表,我该如何实现?
注意:我很乐意在需要时更改计数方法
修改1
感谢@LeonidBeschastny我现在有了工作代码:
getTags = (articles) ->
tags = {}
for article in articles
for tag in article.Tags
tags[tag] = (tags[tag] or 0) + 1
tags = do (tags) ->
keys = Object.keys(tags).sort (a, b) -> tags[b] - tags[a]
{name, count: tags[name]} for name in keys
tags
您可以看到我必须将未排序的tags
地图对象投影到一个新的已排序{name:value}
对象数组中。
感觉这是太多的工作,我想也许原始未分类的对象是一个错误。有没有办法在没有经过这个中间步骤的情况下进入排序数组?
修改2
感谢@hpaulj做了一些时间测试并发现上面的代码与其他可能的解决方案(例如运行的有序堆)相比实际上相当有效。
我现在已将此代码投入生产并且运行良好。
答案 0 :(得分:2)
您可以使用Array::sort
对标记进行排序,然后重建tags
对象:
tags = do (tags) ->
res = {}
keys = Object.keys(tags).sort (a, b) -> tags[b] - tags[a]
for k in keys
res[k] = tags[k]
res
至于插入顺序,mu is too short
是正确的,ECMA规范无法保证。 V8
为文字(非数字)键维护它,但我对其他JS引擎不太确定。
因此,正确的解决方案是使用数组:
tags = do (tags) ->
keys = Object.keys(tags).sort (a, b) -> tags[b] - tags[a]
{name, count: tags[name]} for name in keys
答案 1 :(得分:1)
使用heapq
。这比简单计数然后排序更复杂,但如果我们需要一个运行的排序计数可能会很有用。
使用Python的{1},https://github.com/qiao/heap.js
的Coffeescript翻译heapq
产生
heap = require './heap'
# adapted from
# http://docs.python.org/2/library/heapq.html#priority-queue-implementation-notes
pq = [] # list of entries arranged in a heap
entry_finder = {} # mapping of tasks to entries
REMOVED = '<removed-task>'
counter = [0]
remove_task = (task) ->
# Mark an existing task as REMOVED. return null if not found.
entry = entry_finder[task]
if entry?
delete entry_finder[task]
entry[entry.length-1] = REMOVED
return entry
count_task = (task) ->
entry = remove_task(task)
if entry?
[priority, count, _] = entry
priority += 1
else
counter[0] += 1
count = counter[0]
priority = 1
entry = [priority, count, task]
entry_finder[task] = entry
heap.push(pq, entry)
console.log h = ['one','two','one','three','four','two','one']
for task in h
count_task(task)
console.log entry_finder
console.log pq
alist = heap.nlargest(pq, 10)
for x in alist
[priority, count, task] = x
if task != REMOVED
console.log task, priority, count