Javascript 中的循环排名实施

Circular Ranking implementation in Javascript

在 javascript 中是否有建立非线性排名层次结构的方法,例如 a>b>c>a?

其中类似:

> a>b
true
> b>c
true
> c>a
true

能一直保持一致吗?

您可以创建在转换时改变自身的对象:

let x = { valueOf: () => this.v = ~this.v };
console.log(x < x);

let a = b = c = x;
console.log(a < b && b < c && c < a);

对于不变的对象是不可能的,因为带有比较运算符的 Number 是可传递的。

注意:valueOf 用于 < 到 Number 的隐式转换。 ~this.v 只是在这种情况下缩短初始化的一个技巧,~undefined === -1。之后 this.v-10 之间交替。

这有一个问题,当 valueOf 只被调用一次时它会反转。另一种方法是使用不断增加的计数器。我认为无法检测到 valueOf 调用是否来自比较。

let counter = 0;
let x = { valueOf: () => counter++ };
console.log(x < x);

let a = b = c = x;
console.log(a < b && b < c && c < a);
console.log(x.valueOf());
console.log(a < b && b < c && c < a);

你指的是cyclic order。例如,考虑一年中的几个月:

                       +----> March -----+
                       |                 |
                       |                 v
             +----> February           April -----+
             |                                    |
             |                                    v
   +----> January                                May -----+
   |                                                      |
   |                                                      v
December                                                 June
   ^                                                      |
   |                                                      |
   +----- November                              July <----+
             ^                                    |
             |                                    |
             +----- October           August <----+
                       ^                 |
                       |                 |
                       +--- September <--+

在循环顺序中,说“一月在三月之前”这样的话是没有意义的,因为它并不总是在三月之前。不过,“八月过后,一月在三月前”,“二月后,三月在一月前”之类的话,倒是说得通。

用编程术语来说:

after(August, January, March);   // true
after(February, March, January); // true

还有一些技巧可以让您编写如下代码:

after(August),   January < March; // true
after(February), January > March; // true

以下是让它发挥作用的方法:

const [ March
      , April
      , May
      , June
      , July
      , August
      , September
      , October
      , November
      , December
      , January
      , February ] = cycle();

console.log((after(August),   January < March)); // true
console.log((after(February), January > March)); // true

function* cycle(n = 1, j = 0) {
    for (let i = 0; true; i++, n++) {
        yield {
            valueOf: () => (i + j) % n,
            get after() { j = n - i; }
        };
    }
}

function after(x) {
    return x.after;
}

有趣的是,您知道三月是罗马历的第一个月吗?想想看:

  1. 三月标志着 Spring 的开始,新生活的季节。因此,一年的开始恰逢新生命的开始。
  2. 如果三月是第一个月,那么九月、十月、十一月和十二月分别是七月、八月、九月和十月。因此,它们被称为九月(七分之一)、十月(八分之一)、十一月(九分之一)和十二月(十分之一)。

无论如何,希望对您有所帮助。