假设我有以下数组:
var articles = [
{
id: 7989546,
tags: [
"98#6",
"107#6",
"558234#7"
]
},
//...
]
此数组的每个元素代表(部分)我们网站中的某种内容。它有一个 id ,并标有 人 (#6)和/或 主题 (#7)。
将向用户提供包含建议或推荐标签的cookie,如下所示:
var suggestions = [
"46#6",
"107#6",
"48793#7"
]
请考虑这些标记,例如将向最终用户展示的建议,例如“也许您在阅读中感兴趣......”
suggestions
数组已按标记优先顺序排序。这意味着,第一个标签与用户的关联性高于第二个标签。
现在,我要做的是以相同的方式订购我的articles
数组,即标记优先级。
不应该应用过滤器,因为articles
数组保证包含suggestions
数组中至少有一个标记的元素。
如果我的文章包含标记[ "98#6", "107#6", 558234#7" ]
而另一个文章标记为[ "46#6", "36987#7" ]
,我希望后者成为第一个,因为标记46#6
的优先级高于{{1} 1 {}在107#6
数组中。
如何实现这种排序(使用两个数组)?
注意:很高兴接受jQuery解决方案。
答案 0 :(得分:0)
<强> jsFiddle Demo
强>
只需创建自己的排序功能,然后使用.indexOf
检查标记是否存在。您将不得不决定自己处理的问题是最容易发生碰撞的问题。如果文章标记有优先级1标记,但另一篇文章标记有3个较低优先级标记,谁优先?这里有一些逻辑,在我建议的解决方案中,我只是通过使用建议的长度和总结优先级来总结优先级。如果您愿意,这可以适用于提供不同类型的碰撞检测,但方法基本相同。
第1步:创建比较功能
这将根据tagCount的结果对数组进行降序排序。也就是说,如果tagCount为right返回值6,为left返回值3,则首先排序6。
var compareFn = function(left,right){
return tagCount(right.tags) - tagCount(left.tags);
};
步骤2:创建tagCount“算法”以确定优先级
这简单地优先考虑最早出现的匹配,但也会对多个后来发生的匹配给予一定的权重。它通过从匹配数组的长度中减去匹配的索引来做到这一点(建议)。因此,如果有5个建议,并且第一个建议匹配,那么最终将得到值5(长度= 5 - 索引= 0)。
var tagCount = function(tags){
var count = 0;
for(var i = 0; i < tags.length; i++){
var weight = suggestions.indexOf(tags[i]);
if(weight > -1)
count += tags.length - weight;
}
return count;
}
Stack Snippet
var articles = [
{
id: 7989546,
tags: [
"107#6",
"558234#7"
]
},
{
id: 756,
tags: [
"98#6",
"558234#7"
]
},
{
id: 79876,
tags: [
"98#6",
"107#6",
"558234#7"
]
},
{
id: 7984576,
tags: [
"98#6",
"107#6",
"46#6"
]
}
];
var suggestions = [
"46#6",
"107#6",
"48793#7"
];
var compareFn = function(left,right){
return tagCount(right.tags) - tagCount(left.tags);
};
var tagCount = function(tags){
var count = 0;
for(var i = 0; i < tags.length; i++){
var weight = suggestions.indexOf(tags[i]);
if(weight > -1)
count += tags.length - weight;
}
return count;
}
var a = articles.sort(compareFn);
console.log(a);
document.querySelector("#d").innerHTML = JSON.stringify(a);
<div id="d"></div>
答案 1 :(得分:0)
我的方法:按相关性得分之和排序
给你:
var articles = [
{
id: 7989546,
tags: [
"98#6",
"107#6",
"558234#7"
]
},
{
id: 8000000,
tags: [
"107#6",
"107#10",
"558234#7",
"5555#1"
]
},
{
id: 8333000,
tags: [
"46#6",
"107#6",
"666234#7",
"107#6"
]
}
];
var suggestions = [
"46#6",
"107#6",
"48793#7"
];
您希望按标签排序articles
,而标记排名则在suggestions
中定义。一个简单的方法是:
步骤1)对于每篇文章,获取suggestion
中每个标记的索引。如果它不存在,请丢弃。
给出建议[&#34; a&#34;,&#34; b&#34;,&#34; c&#34;]
文章标签[&#34; a&#34;,&#34; b&#34;,&#34; zzzz&#34;,&#34; yyyy&#34;]
将映射到索引 [0,1] (最后两个标记被丢弃,因为它们在建议列表中不存在)
步骤2)计算相关程度。排名较高的标签(较小的索引)会产生更大的价值(参见下面的函数degreeOfRelevance()
)。
步骤3)总计相关度,并按此值排序。因此,包含更高排名标签的文章(基于建议)将产生更高的总分。
简单示例:
文章&lt; 100&gt;标签:[a,b,c]
文章&lt; 200&gt;标签:[b,c]
文章&lt; 300&gt;标签:[c,d,e,f]
给出建议: [a,b,c]
文章将映射到分数:
文章&lt; 100&gt; index:[0,1] ===&gt;总分:3 + 2 = 5
文章&lt; 200&gt; index:[1] ===&gt;总分:2
文章&lt; 300&gt; index:[2] ===&gt;总分:1
因此,文章&lt; 100&gt;按分数排序时,它被列为最相关的文档
以下是此方法的工作代码:
function suggest(articles, suggestions){
function degreeOfRelavance(t){
return suggestions.length - suggestions.indexOf(t);
}
function weight(tags){
return (tags.map(degreeOfRelavance)).reduce(function(a,b){
return a+b
},0);
}
function relatedTags(a){
return a.tags.filter(function(t){
return suggestions.indexOf(t)>=0
});
}
articles.sort(function(a,b){
return weight(relatedTags(a)) < weight(relatedTags(b))
});
return articles;
}
// See the output
console.log(suggest(articles,suggestions));