对目标进行排序以最小化序列重复

时间:2016-12-28 04:41:36

标签: arrays node.js algorithm sorting array-difference

好的,我有一组websocket客户端连接。想象一下,这个数组包含与几台不同机器的连接。想象一下,每个不同的字母(1,2,3等)代表不同的主机。它可能看起来像这样:

const conns = [1,1,1,3,3,1,3,2,2,2,2,3,2,1,1,2,2];

我想做的是对数组进行排序:

const conns = [1,2,3,1,2,3,1,2,3, ... etc];

理由是如果客户没有回复,我不想重试同一主机,我想尝试向另一台主机上的客户端发送消息,并且只回到原来的主持人。这基本上就像一个循环型的东西。

我认为对数组进行排序的最佳方法是:

  1. 找到数组中所有不同的主机(唯一字母)
  2. 迭代这个唯一的列表,并在我离开时拼接原始数组中的项目。
  3. 以下是我对上述算法的JS代码:

    const list = [1,2,3,4,5,1,1,1,1,1,2,3,4,5,1,2,11,3,3,3,3,3,4,4,4,1,1,1];
    
    const _ = require('lodash');
    
    function findAndRemoveFirstMatch(m, list){
        for(var i = 0; i < list.length; i++){
            if(m === list[i]){
                return list.splice(i,1)[0];
            }
        }
    }
    
    function getSorted(list){
    
        const ret = [];
    
        const set = _.uniqBy(list, function(x){
            return x;
        });
    
        while(list.length > 0){
    
            var i = 0;
            while(i < set.length && list.length > 0){
                var item;
                if(item  = findAndRemoveFirstMatch(set[i],list)){
                    ret.push(item);
                }
                i++;
            }
    
        }
    
        return ret;
    
    }
    
    console.log(getSorted(list));
    

    //根据上述输入,我们得到:

    [ 1, 2, 3, 4, 5, 11, 1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 3, 4, 1, 3, 4, 1, 3, 1, 3, 1, 1, 1 ]
    

    我对这段代码并不感到自豪,并且想知道是否有更好的方法来实现它。以上内容适用于此输入,但寻找一种清理它并使其更通用的好方法。

    有更好/更快的方法吗?

1 个答案:

答案 0 :(得分:1)

您可以采用不同的方式:

  • 排序输入 - 稍后会有所帮助

  • 找到相等元素的最大数量(在您的示例中为10,对于element = 1), cnt

  • 创建 cnt 存储桶以在其上分发元素

  • 按顺序将元素按顺序排列到循环原则的下一个桶中

  • 合并水桶

这样你最终会得到更长的系列,比开始时少1个。

[1, 2, 4, 1, 2, 4, 1, 2, 4, 1, 3, 4, 1, 3, 4, 1, 3, 5, 1, 3, 5, 1, 3, 11, 1, 3, 1, 3]

不好的情况是当一个元素出现超过n / 2次,但这是不可避免的。

var list = [1,2,3,4,5,1,1,1,1,1,2,3,4,5,1,2,11,3,3,3,3,3,4,4,4,1,1,1];
var a = list.sort(function(a, b) { return a - b; });
var cnt = a.reduce(function(res, cur) {
  if (cur == res[0]) 
    return [cur, res[1]+1, Math.max(res[1]+1, res[2])]
  else
    return [cur, 1, Math.max(1, res[2])];
}, [null, 0, 0])[2];

var buckets = [];
for (var i = 0; i < cnt; i++)
  buckets[i] = [];

var j = 0;
for (var i = 0; i < a.length; i++) {
  buckets[j].push(a[i]);
  j = (j+1)%cnt;
}

var res = buckets.reduce(function(r, cur) {
  return r.concat(cur);
});

如果您从头开始坚持完整的密钥列表,也可以:

var list = [1,2,3,4,5,1,1,1,1,1,2,3,4,5,1,2,11,3,3,3,3,3,4,4,4,1,1,1];
var a = list.sort(function(a, b) { return a - b; });
var cnt = a.reduce(function(res, cur) {
    if (cur == res[0]) 
        return [cur, res[1]+1, Math.max(res[1]+1, res[2])]
    else
        return [cur, 1, Math.max(1, res[2])];
}, [null, 0, 0])[2];

var buckets = [];
for (var i = 0; i < cnt; i++)
    buckets[i] = [];

var j = 0;
var cur = null;
for (var i = 0; i < a.length; i++) {
    if (cur != a[i]) 
        j = 0;
    buckets[j].push(a[i]);
    j = j+1;
}

var res = buckets.reduce(function(r, cur) {
    return r.concat(cur);
});