【问题标题】:Sort array with goal to minimize sequence repeat以最小化序列重复为目标对数组进行排序
【发布时间】:2017-05-12 08:20:33
【问题描述】:

好的,我有一组 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. 遍历这个唯一的列表,然后从原始数组中拼接出项目。

这是我对上述算法的 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 ]

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

有没有更好/更快的方法来做到这一点?

【问题讨论】:

  • 只需创建一个Set object 并将初始数组传递给构造函数。这将为您提供所有独特项目的可迭代列表。
  • @jfriend00 是的,但这是否适用于对象而不是原语?实际上,我使用的是对象而不是字符串。我想我可以将对象映射到原始 id,然后将其传递给 set 构造函数?谢谢你的好主意
  • 是的,Set 适用于对象。这是它的一个真正优势,因为它不需要字符串作为键。
  • 好吧,它的所有元素都将被添加,但不会有重复。给定的键只能在 Set 中出现一次。
  • 它使用实际的对象引用本身。它不会比较对象是否包含相同的属性/值 - 只是它是否实际上是相同的对象引用。与objA === objB的逻辑相同。

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


【解决方案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);
});

如果你一开始就坚持完整的key列表,也是可以的:

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

【讨论】:

  • 我很困惑,理想情况下应该是 [1,2,3,4,11,1,2,3,4...] 等?
猜你喜欢
  • 2017-01-04
  • 2019-07-01
  • 1970-01-01
  • 2011-12-06
  • 1970-01-01
  • 2015-07-27
  • 2018-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多