英文:
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 -->
<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?
答案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
基本上是一样的,只是将 a
和 b
交换了。
现在回到你的问题。首先,你描述的第三个 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.ascending
和 d3.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) => a - b
) is testing for null
before comparing the numbers:
function ascending(a, b) {
return a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= 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 < 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));
<!-- 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 > 42);
console.log(NaN < 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) => a - b));
console.log([10, NaN, 2, 3, 7].sort((a, b) => 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 NaN
s at the end (and "10"
before "2"
, 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()
处理所有非数值值,如NaN
和undefined
。在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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论