【问题标题】:Complex array ordering复杂数组排序
【发布时间】:2015-07-13 18:17:23
【问题描述】:

假设我有以下数组:

var articles = [
     {
          id: 7989546,
          tags: [
              "98#6",
              "107#6",
              "558234#7"
          ]
     },
     //...
]

该数组的每个元素(部分)代表我们网站中的某种内容。它有一个 id 并带有 people (#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" ] 的文章,我希望后者排在第一位,因为 suggestions 中标签 46#6 的优先级高于 107#6数组。

我怎样才能实现这种排序(使用两个数组)?

注意:我们很乐意接受 jQuery 解决方案。

【问题讨论】:

  • 假设你的数据量不是太大,你总是可以自己写一个O(n^2)的排序方法,比如冒泡排序或者选择排序。这应该更容易满足您的需求
  • 有点困惑。 “46#6”的优先级高于“107#6”。您正在将一个数组的第一个索引与另一个数组的第二个索引进行比较。这是故意的吗?
  • @ChristianHain "46#6" 比 "107#6" 具有更高的优先级,因为 "46#6" 在 suggestions 数组中位于 "107#6" 的顶部。但是,您说sugesstions 数组上的标记索引定义了它的优先级是对的。索引越小,优先级越高
  • 你怎么知道“107#6”顶部的“46#6”。我不明白你为什么要跳过“98#6”
  • @ChristianHain 你应该看看我在问题中展示的suggestions 数组。您可以看到它包含三个元素:[ "46#6", "107#6", "48793#7" ]46#6 是第一,107#6 是第二,因此46#6 具有更高的优先级。我忽略了"98#6",因为它不在我的suggestions 数组中,因此在订购时应该忽略它

标签: javascript jquery arrays


【解决方案1】:

jsFiddle Demo

只需创建自己的排序函数,然后使用.indexOf 来检查标签是否存在。您将不得不决定自己处理的问题是对碰撞最有意义的问题。如果一篇文章被标记为优先级为 1 的标签,而另一篇文章被标记为 3 个较低优先级的标签,那么谁获得优先权?那里涉及一些逻辑,在我建议的解决方案中,我只是通过使用建议的长度并对优先级求和来获得优先级的总和。如果您愿意,可以对其进行调整以提供不同类型的碰撞检测,但方法基本相同。

第 1 步:创建比较函数

这将根据 tagCount 的结果对数组进行降序排序。也就是说,如果 tagCount 的右返回值为 6,左返回值为 3,则先排序为 6。

var compareFn = function(left,right){
    return tagCount(right.tags) - tagCount(left.tags);
};

第 2 步:创建用于确定优先级的 tagCount“算法”

这只是为最早出现的匹配赋予优先级,但也会为多个后来出现的匹配赋予一些权重。它通过从匹配数组的长度中减去匹配的索引(建议)来做到这一点。因此,如果有 5 个建议,并且第一个建议匹配,那么最终的值将是 5 (length=5 - index=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;
}

堆栈片段

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);
&lt;div id="d"&gt;&lt;/div&gt;

【讨论】:

    【解决方案2】:

    我的方法:按相关性得分总和排序

    给你:

    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 中定义。一种简单的方法是:

    Step 1) 对于每篇文章,获取suggestion中存在的每个标签的索引。如果不存在,则丢弃。

    给定建议 ["a","b","c"]

    文章标签 ["a","b","zzzz","yyyy"]

    将映射到索引[0,1](最后两个标签被丢弃,因为它们不存在于建议列表中)

    步骤 2) 计算相关度。排名较高的标签(较小的索引)产生更大的价值(参见下面的函数degreeOfRelevance())。

    Step 3) 对总相关度求和,并按此值排序。因此,包含更高排名标签(基于建议)的文章将产生更高的总分。

    简单示例:

    文章 带有标签:[a,b,c]

    文章 带有标签:[b,c]

    文章 带有标签:[c,d,e,f]

    给出建议: [a,b,c]

    文章将映射到分数:

    文章索引:[0,1] ===>总分:3+2 = 5

    文章索引:[1] ===>总分:2

    文章索引:[2] ===>总分:1

    因此,文章 在按分数排序时被列为最相关的文档

    下面是这种方法的工作代码:

    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));
        
    

    【讨论】:

      猜你喜欢
      • 2014-09-11
      • 2021-12-21
      • 1970-01-01
      • 2016-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-01
      相关资源
      最近更新 更多