【问题标题】:Finding the middle index between any two indexes in a circular array查找循环数组中任意两个索引之间的中间索引
【发布时间】:2016-05-17 11:56:00
【问题描述】:

我有一个数组和三个索引:

var arr = ['a', 'b', 'c', 'd'];
var f = 0; // first element
var l = arr.length - 1; // last element
var c = 0; // current element

我正在尝试编写一个使索引c 循环遍历数组的函数。要求是它永远不会达到索引l。因此,每当c 达到某个值时,fl 也需要增加。

我认为作为 c 限制的合理值是 f 和 l 之间的中点。我写的函数是这样的:

var mod = function(x, m) {
    var r = x%m;
    return r<0 ? r+m : r;
}

while (true) {
    console.log('f', f, 'l', l, 'c', c);
    if (c == l) {
       console.log('error');
    }

    c = mod(c + 1, arr.length);

   if (c > mod(l - f, arr.length) / 2) {
      f = mod(f + 1, arr.length);
      l = mod(l + 1, arr.length);
   }
}

显然,它不起作用。是否有一个很好的简单公式来使用模运算符来获得我想要的东西,或者这种方法完全错误?

这是一个尝试的小提琴:https://jsfiddle.net/wku37h9e/2/

编辑: 解释这样做的目的会有点长。假设在数组中存储了我必须不断移动的外部元素的位置。当c 接近l 时,我推进所有索引。图形上会是这样的:

1. [f|c] [   ] [   ] [ l ]
2. [ f ] [ c ] [   ] [ l ]
3. [ l ] [ f ] [ c ] [   ] // here I start moving things around
4. [   ] [ l ] [ f ] [ c ]
5. [ c ] [   ] [ l ] [ f ]
6. [ f ] [ c ] [   ] [ l ]

等等。数组中的元素越多,索引之间的距离就会越大。

我还使用不同于普通版本的 mod 来考虑负数。

我希望现在清楚一点

【问题讨论】:

  • 你为什么要这样做?请添加示例。
  • 我添加了视觉解释
  • 起始位置 1 和位置 5 导致不同的结果。 c的位置应该移动fl吗?
  • 它应该是这样工作的。当cl 太接近时,l 会向前移动,f 也会向前移动

标签: javascript arrays modulo


【解决方案1】:

作为c 的限制的合理值我认为是fl 之间的中间点

在 mod len 中找到两个值之间的平均值,lowhigh

function midPoint(low, high, len) {
    var mid;
    low %= len;
    high %= len;
    while (low < 0) low += len; // these two lines are the
    while (high < low) high += len; // most important for direction
    mid = (low + high) / 2; // mean average
    mid %= len; // convert back to our mod
    return mid;
}

原来如此

// works as expected beyond range of mod
midPoint( 1, -1, 9); // middle of 1..8 (mod 9) = 4.5
midPoint(-7,  5, 9); // middle of 2..5 (mod 9) = 3.5
midPoint(-6, 12, 9); // middle of 3..3 (mod 9) = 3
// and
midPoint( 2,  5, 9); // middle of 2..5 (mod 9) = 3.5
midPoint( 5,  2, 9); // middle of 5..2 (mod 9) = 8 (we went the other way around)

在整个计算完成之前,您实际上不必强制执行 mod,所以如果您真的想要,您可以执行以下操作,但您会在循环中失去方向

function midPoint(A, B, len) {
    var mid;
    mid = (A + B) / 2; // mean average
    mid %= len; // convert back to our mod
    while (mid < 0) mid += len; // always positive
    return mid;
}

请注意这里

midPoint(-6, 3, 9); // middle of 3..3 (mod 9) = 7.5
midPoint( 3, 3 + 0 * 9, 9); // middle of 3..3 (mod 9) = 3
midPoint( 3, 3 + 1 * 9, 9); // middle of 3..3 (mod 9) = 7.5
midPoint( 3, 3 + 2 * 9, 9); // middle of 3..3 (mod 9) = 3

3..3 (mod 9) 的中点是 37.5,这是 true,但我们现在走的路取决于 k(其中 @987654335 @)

【讨论】:

  • 这似乎是我需要的,但仍然无法正常工作。我总是从这个开始:f = 0, l=3, c=0 and len=4。所以它是这样的:c=0 | f=0, l=3, m=1.5; c=1 | f=0, l=3, m=1.5; c=2 | f=1, l=0, m=2.5; c=3 | f=2, l=1, m=3.5;此时 m 停留在 3.5,经过一些迭代后 c 将达到 l。我在想也许我必须把 m 向下舍入
【解决方案2】:

我不确定我是否理解 - 当我定义一切正常的 mod 函数时:

function test() {
    var i=0;
    var arr = ['a', 'b', 'c', 'd'];
    var f = 0; // first element
    var l = arr.length - 1; // last element
    var c = 0; // current element
    while (true && i < 1000) {
        ++i;
        console.log('f', f, 'l', l, 'c', c);
        if (c == l) {
           console.log('error');
           break;
        }

        c = mod(c + 1, arr.length);

        if (c > mod(l - f, arr.length) / 2) {
           f = mod(f + 1, arr.length);
           l = mod(l + 1, arr.length);
        }
    }
}
function mod(a,b) { return a % b;}

似乎循环 c 通过可能的值,cl 的(不断重新计算的)值不同...但我不明白你试图应用到 @ 的算法987654324@ 和l 那里

【讨论】:

  • 我编辑了问题,添加了一些视觉解释和 mod 函数定义。您的版本确实可以正常工作,但我最初使用不同的 mod 函数来考虑负数。
【解决方案3】:

我只用数组长度的一半加上c 计算lf 是下一个索引。所有数字都是正数。

                            c   f   l
1. [ c ] [   ] [ l ] [ f ]  0   3   2  l = length / 2 + c, f = l + 1  both mod length
2. [ f ] [ c ] [   ] [ l ]  1   0   3
3. [ l ] [ f ] [ c ] [   ]  2   1   0
4. [   ] [ l ] [ f ] [ c ]  3   2   1
5. [ c ] [   ] [ l ] [ f ]  0   3   2
6. [ f ] [ c ] [   ] [ l ]  1   0   3

var arr = ['a', 'b', 'c', 'd'],
        c, f, l;

for (c = 0; c < arr.length; c++) {
    l = (arr.length / 2 + c) % arr.length;
    f = (l + 1) % arr.length;
    document.write('c:' + c + ' f: ' + f + ' l: ' + l + '<br>');
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多