我需要一个函数来改组元素数组,但是要保持元素之间的最小距离为2。

让我来解释一下我的情况,我有一个不间断的输入,该输入每200ms一直发送一次发送给我的单词。我还有一个带有预定义单词的唯一数组。

我收到的每个单词都会检查是否可以,如果在我的条件下可以,我想将其放入数组中。但是,在那一刻,我不再需要唯一的数组,所以我的数组中可能会有双精度字,实际上,我想让双精度字适合我的情况。

好的,这就是问题所在,我收到的每个OK单词,我都希望将其放入数组中,然后将其洗牌,它可以是双精度的,但是在这种情况下,我想让这个单词与数组中其他相同的词。

例:
唯一数组:[foo,bar,baz,qux]
我启动程序,每200毫秒发送一次文字给我。
获得:fubar>确定
插入:[foo,bar,baz,qux,fubar]
得到:橙色>确定
插入:[foo,bar,baz,qux,fubar,橙色]
得到:石灰>确定
插入:[foo,bar,baz,qux,fubar,橙色,酸橙]
得到:qux>确定(双)

正确插入:[foo,bar,baz,qux,fubar,橙色,石灰,qux]
正确插入:[foo,qux,bar,baz,qux,fubar,橙色,酸橙]
插入错误的方式:[foo,bar,baz,qux,qux,fubar,橙色,酸橙]

第一个距离为3,第二个距离为2 ...
第三个也是错误的,距离为0。

任何人都可以给我一个好的方法和/或逻辑来做到这一点?对于类似情况,最小距离= 2。

先感谢您。



编辑1:
用户jfriend00出现了数组充满双精度数的可能性,假设它们都具有最小距离,并且要插入的下一个元素没有合适的正确位置,那么我就不能插入它。



编辑2:
我还认为,必须避免将插入插入可能无法插入下一个插入的位置,例如:

得到:苹果>确定
(A)正确插入:[巴兹,古克斯,富巴,橙子,酸橙,苹果]

得到:qux>确定(双)
(A)正确插入:[巴兹,古克斯,富巴,橙子,古克斯,酸橙,苹果]
(B)插入错误的方式:[巴兹,古克斯,富巴,橙子,酸橙,古克斯,苹果]

在这里,插入片段将被插入距离3(B)的qux“截断”。

得到:qux>确定(双)
(A)插入正确的方式:[巴兹,古克斯,富巴,橙子,古克斯,石灰,苹果,古克斯]
(B)插入错误的方式:[巴兹,古克斯,富巴,橙子,酸橙,古克斯,苹果]

最佳答案

我必须承认,这并不简单。让我们从一些辅助函数开始:

Array.prototype.unique = function() {
    var i = 0, t = 1, l = (this.length >>> 0) - 1;
    for (; i < l; t = ++i + 1)
        while ((t = this.indexOf(this[i], t)) !== -1)
            this.splice(t, 1);
    return this;
};
Array.prototype.count = function(item) {
    var i = 0, t = 0;
    while (i = this.indexOf(item, i) + 1) t++;
    return t;
};
Array.prototype.remove = function(item) {
    var i = this.indexOf(item);
    if (i !== -1) this.splice(i, 1);
    return this;
};


我希望含义很清楚,即使代码看起来晦涩难懂。对于较旧的浏览器(基本上是IE8-),也有用于Array.prototype.indexOf的polyfill。

现在的代码:

function shuffleArray(array, previous) {
    if (!array.length) return array;
    // The list of unique items in the array
    var univals = array.slice().unique(),
        idx, pivot, rest;
    if (previous != null)
        // The array can't start with the previous element
        univals.remove(previous);

    while (univals.length) {
        // We choose an element from the possible ones
        idx = Math.floor(Math.random() * univals.length);
        pivot = univals[idx];
        // We try to shuffle the rest of the array.
        rest = shuffleArray(array.slice().remove(pivot), pivot);
        // If we got a shuffled array, we're done.
        // Else, we remove our pivot element from the possible ones
        if (rest != null)
            return [pivot].concat(rest);
        else univals.splice(idx, 1);
    }
    return null;
}


用法是:

shuffleArray(array);


您可以添加第二个可选参数,以使其避免从某个元素开始。在函数本身内部递归使用。如果得到null,则无法使用给定的约束对数组进行混洗。

请记住,可以优化此算法。特别是,您可以对其进行更改,以便它不是递归的,而是迭代的,并且更适合于较大的数组。

07-27 15:39