Javascript中的循环排名实现

时间:2017-10-06 16:26:39

标签: javascript ranking

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

类似于:

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

总能保持一致吗?

2 个答案:

答案 0 :(得分:2)

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

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

按照循环的顺序,说“1月来到三月之前”是没有意义的,因为它并不总是在三月之前。但是,说“八月之后,三月之前到三月之前”和“二月之后,三月之前一月之前”这样的事情确实有意义。

用编程术语表示:

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

还有一些hack可以让你编写这样的代码:

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

有趣的是,你知道3月是罗马历法的第一个月吗?想一想:

  1. 三月标志着春天的开始,即新生活的季节。因此,今年年初恰逢新生活的开始。
  2. 如果三月是第一个月,那么九月,十月,十一月和十二月分别是第7个月,第8个月,第9个月和第10个月。因此,它们被称为9月(隔7代),10月(8月代表8月),11月(9月份为nona)和12月份(10月份为deca)。
  3. 无论如何,希望有所帮助。

答案 1 :(得分:1)

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

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

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

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

注意:valueOf用于隐式转换为<的数字。 ~this.v只是缩短本例初始化~undefined === -1的技巧。之后this.v会在-10之间切换。

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

&#13;
&#13;
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);
&#13;
&#13;
&#13;