好的,我有一组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];
理由是如果客户没有回复,我不想重试同一主机,我想尝试向另一台主机上的客户端发送消息,并且只回到原来的主持人。这基本上就像一个循环型的东西。
我认为对数组进行排序的最佳方法是:
以下是我对上述算法的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 ]
我对这段代码并不感到自豪,并且想知道是否有更好的方法来实现它。以上内容适用于此输入,但寻找一种清理它并使其更通用的好方法。
有更好/更快的方法吗?
答案 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);
});