Порядок вывода данных в d3.sort() - по возрастанию или по убыванию

Я попытался запустить следующий код:

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

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

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

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

И расхождения в выводе между сортировкой по возрастанию и убыванию поставили меня в тупик.

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]

Наблюдаемые учебные пособия D3, похоже, не затрагивают эту проблему. На самом деле, там есть некоторые другие моменты (относительно того, что d3.count() может подсчитывать строки), которые также оказались неверными, когда я запустил код. Поэтому я не мог полагаться на https://observablehq.com/@d3/

Кто-нибудь знает, ожидается ли вывод или почему порядок такой, как показано в выводе?

какой результат вы ожидаете для значений null и undefined?

Nina Scholz 06.02.2023 21:04

Я ожидал, что сортировка по-прежнему будет учитывать значения NaN и undefined и что-то с ними делать. Но я ожидаю некоторой согласованности между сортировкой по возрастанию и убыванию.

aashima 06.02.2023 21:14
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
2
73
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В JavaScript функция sort() обрабатывает все нечисловые значения, такие как NaN и undefined. В JavaScript NaN является особым значением и не равно никакому другому значению, в том числе и самому себе, поэтому при попытке отсортировать массив, содержащий NaN, он появляется последним в порядке возрастания. undefined это пропущенное значение и считается меньшим, чем любое другое значение, поэтому undefined появляется последним как в порядке возрастания, так и в порядке убывания. Это поведение не характерно для D3, это просто язык JavaScript.

NaN появляется последним в порядке возрастания, так почему же тогда он появляется вторым в порядке убывания? **[Log] [2, 3, 7, 10, NaN]****[Log] [10, NaN, 7, 3, 2]**

aashima 06.02.2023 21:13
Ответ принят как подходящий

Это проблема не D3, а javascript.

Если вы посмотрите на исходный код, единственное, что отличает по возрастанию от обычного сравнения (то есть (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.info(), неверен, 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.info([10, NaN, 2, 3, 7].sort(ascending));
console.info([10, NaN, 2, 3, 7].sort(descending));

Здесь происходит то, что любое сравнение с NaN вернет false:

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

Поэтому ожидаем результаты D3 (а также обратите внимание, что между d3.ascending и d3.descending нет расхождений). На самом деле, вы получите те же результаты с простым JavaScript:

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

Наконец, стоит отметить, что, поскольку буква N стоит после всех чисел, JavaScript sort без функции сравнения поместит NaN в конец (и "10" перед "2", очевидно):

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

Привет, спасибо, что нашли время, чтобы внести некоторую ясность. Теперь я понимаю, что d3.ascending и d3.descending на самом деле не играют здесь роли. Вывод такой же, как и при обычной сортировке Javascript. Однако я не понимаю, что вы подразумеваете под этим - «описанный вами вывод для третьего console.info() неверен, NaN никогда не находится в последней позиции». Я запустил фрагмент кода, который я опубликовал, а также простой код Javascript в последних двух фрагментах кода, включенных в ваш ответ, и вижу, что NaN находится на последней позиции. Не могли бы вы объяснить?

aashima 10.02.2023 12:54

@aashima Sort зависит от реализации, вы, вероятно, используете Safari. Попробуйте Chrome или Firefox, вы увидите разницу.

Gerardo Furtado 10.02.2023 15:50

Вау, ты прав! Я вижу другой результат в Chrome. Спасибо, это так помогло!

aashima 10.02.2023 18:40

Другие вопросы по теме