d3.sort()中的输出数据顺序 – 升序 vs 降序

huangapple go评论72阅读模式
英文:

Order of output data in d3.sort() - ascending vs descending

问题

I tried running the following code:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

<script src="https://d3js.org/d3.v7.min.js"></script>
<script>

console.log([10,2,3,7].sort(d3.ascending)); // 1
console.log([10,2,3,7].sort(d3.descending)); // 2

console.log([10,NaN,2,3,7].sort(d3.ascending)); // 3
console.log([10,NaN,2,3,7].sort(d3.descending)); // 4

console.log([10,undefined,2,NaN,3,7].sort(d3.ascending)); // 5
console.log([10,undefined,2,NaN,3,7].sort(d3.descending)); // 6
</script>

<!-- end snippet -->

And the discrepancies in output between the ascending and descending order sorting has me stumped.

CONSOLE OUTPUT:
[Log] [2, 3, 7, 10] 
[Log] [10, 7, 3, 2] 
**[Log] [2, 3, 7, 10, NaN]**
**[Log] [10, NaN, 7, 3, 2]**
[Log] [2, 7, 10, NaN, 3, undefined]
[Log] [10, 7, 2, NaN, 3, undefined]

The observable D3 tutorials don't seem to address this. In fact, there appears to some other points there (regarding d3.count() being able to count strings) which also proved to be wrong when I ran the code. Therefore, I could not rely on https://observablehq.com/@d3/

Does anyone know if the output is expected or why the order is as shown in the output?

英文:

I tried running the following code:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

&lt;script src=&quot;https://d3js.org/d3.v7.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;

console.log([10,2,3,7].sort(d3.ascending));  // 1
console.log([10,2,3,7].sort(d3.descending));  // 2

console.log([10,NaN,2,3,7].sort(d3.ascending));  // 3
console.log([10,NaN,2,3,7].sort(d3.descending));  // 4

console.log([10,undefined,2,NaN,3,7].sort(d3.ascending)); // 5
console.log([10,undefined,2,NaN,3,7].sort(d3.descending));  // 6
&lt;/script&gt;

<!-- end snippet -->

And the discrepancies in output between the ascending and descending order sorting has me stumped.

CONSOLE OUTPUT:
[Log] [2, 3, 7, 10] 
[Log] [10, 7, 3, 2] 
**[Log] [2, 3, 7, 10, NaN]**
**[Log] [10, NaN, 7, 3, 2]**
[Log] [2, 7, 10, NaN, 3, undefined]
[Log] [10, 7, 2, NaN, 3, undefined]

The observable D3 tutorials don't seem to address this. In fact, there appears to some other points there (regarding d3.count() being able to count strings) which also proved to be wrong when I ran the code. Therefore, I could not rely on https://observablehq.com/@d3/

Does anyone know if the output is expected or why the order is as shown in the output?

答案1

得分: 3

这不是一个D3的问题,而是一个JavaScript的问题。

如果你查看源代码,ascending 唯一与基本比较不同的地方(即 (a, b) => a - b)是在比较数字之前测试是否为 null

function ascending(a, b) {
    return a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

descending 基本上是一样的,只是将 ab 交换了。

现在回到你的问题。首先,你描述的第三个 console.log() 的输出是不正确的,NaN 从来不会出现在最后位置:

function descending(a, b) {
  return a == null || b == null ? NaN : b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}

function ascending(a, b) {
  return a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}

console.log([10, NaN, 2, 3, 7].sort(ascending));
console.log([10, NaN, 2, 3, 7].sort(descending));

这里发生的是,与 NaN 的任何比较都将返回 false

console.log(NaN > 42);
console.log(NaN < 42);
console.log(NaN === 42);

因此,D3的结果是预期的(还要注意 d3.ascendingd3.descending 之间没有差异)。实际上,使用普通的JavaScript也会得到相同的结果:

console.log([10, NaN, 2, 3, 7].sort((a, b) => a - b)); 
console.log([10, NaN, 2, 3, 7].sort((a, b) => b - a));

最后,值得一提的是,由于字母 N 出现在所有数字之后,没有比较函数的JavaScript sort 会将 NaN 放在末尾(显然将 "10" 放在 "2" 之前):

console.log([10, NaN, 2, 3, 7].sort()); 
英文:

That's not a D3 issue, but a javascript one.

If you look at the source code, the only thing ascending does differently from a basic comparison (i.e., (a, b) =&gt; a - b) is testing for null before comparing the numbers:

function ascending(a, b) {
    return a == null || b == null ? NaN : a &lt; b ? -1 : a &gt; b ? 1 : a &gt;= b ? 0 : NaN;
}

descending is pretty much the same thing, but with a and b swapped.

Now back to your question. First of all, the output you described for the third console.log() is incorrect, NaN is never at the last position:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function descending(a, b) {
  return a == null || b == null ? NaN : b &lt; a ? -1 : b &gt; a ? 1 : b &gt;= a ? 0 : NaN;
}

function ascending(a, b) {
  return a == null || b == null ? NaN : a &lt; b ? -1 : a &gt; b ? 1 : a &gt;= b ? 0 : NaN;
}

console.log([10, NaN, 2, 3, 7].sort(ascending));
console.log([10, NaN, 2, 3, 7].sort(descending));

<!-- end snippet -->

What's happening here is that any comparison with NaN will return false:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

console.log(NaN &gt; 42);
console.log(NaN &lt; 42);
console.log(NaN === 42);

<!-- end snippet -->

Therefore, the D3 results are expected (and also note that there's no discrepancy between d3.ascending and d3.descending). Actually, you get the same results with plain JavaScript:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

console.log([10, NaN, 2, 3, 7].sort((a, b) =&gt; a - b)); 
console.log([10, NaN, 2, 3, 7].sort((a, b) =&gt; b - a));

<!-- end snippet -->

Finally, it's worth mentioning that since the letter N comes after all the numbers, the JavaScript sort without the comparing function will put the NaNs at the end (and &quot;10&quot; before &quot;2&quot;, obviously):

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

console.log([10, NaN, 2, 3, 7].sort()); 

<!-- end snippet -->

答案2

得分: 0

在JavaScript中,函数sort()处理所有非数值值,如NaNundefined。在JavaScript中,NaN是一个特殊值,不等于任何其他值,包括它自己,这就是为什么当你尝试对包含NaN的数组进行排序时,它会出现在升序的最后。undefined是一个缺失的值,被认为小于任何其他值,这就是为什么undefined会在升序和降序排序中都出现在最后。这种行为不仅限于D3,它是JavaScript语言的通用行为。

英文:

In JavaScript, the function sort() handles every non-numeric values like NaN and undefined. In JavaScript NaN is a special value and is not equal to any other value, including itself, that's why when you try to sort an array that contains NaN, it apears last in the ascending order. undefined it's a missing value and is considered less than any other value, that's why undefined appears last in both the ascending and descending order. This behavioris not specific to D3, it's just the JavaScript language.

huangapple
  • 本文由 发表于 2023年2月7日 03:54:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75365960.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定