Метод
sort()
сортирует элементы массива на месте и возвращает ссылку на тот же массив, теперь отсортированный. И мы также можем указать функцию сравнения, при которой применяется метод сортировки. — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Но стабильна ли функция сортировки в React Native? Давайте проверим это.
Мы говорим, что сортировка стабильна, если она сохраняет порядок элементов, которые имеют одинаковые значения для сравнения. Например, мы применяем функцию сортировки с index
в качестве ключа сортировки с возрастанием к массиву, например
const list = [ { name: 'name-1', index: 2, }, { name: 'name-2', index: 0, }, { name: 'name-3', index: 1, }, { name: 'name-4', index: 0, }, { name: 'name-5', index: 0, }, { name: 'name-6', index: 0, }, { name: 'name-7', index: 0, }, ];
и получить вывод как
const list = [ { name: 'name-2', index: 0, }, { name: 'name-4', index: 0, }, { name: 'name-5', index: 0, }, { name: 'name-6', index: 0, }, { name: 'name-7', index: 0, }, { name: 'name-3', index: 1, }, { name: 'name-1', index: 2, }, ];
тогда мы говорим, что этот метод сортировки стабилен, потому что он сохраняет порядок элементов name-2
, name-4
, name-5
, name-6
, name-7
, которые имеют тот же ключ сортировки, что и они.
Наоборот, сортировка нестабильна, если может нарушить порядок элементов с одинаковым ключом сортировки. Это не говорит о том, что это нарушит порядок для всех возможных входных данных, но если есть хотя бы один ввод, который нарушает порядок, он нестабилен.
А потом давайте проверим, стабильно ли это на React Native?
Мы можем создать пример проекта по инструкции (https://reactnative.dev/) или следовать руководству (https://kxie0124.medium.com/implementing-a-sticky-banner-with-animations- in-react-native-df5f619a6bb8).
И добавьте следующий код в App.tsx
, прямо над оператором return
const list = [ { name: 'name-1', index: 2, }, { name: 'name-2', index: 0, }, { name: 'name-3', index: 1, }, { name: 'name-4', index: 0, }, { name: 'name-5', index: 0, }, { name: 'name-6', index: 0, }, { name: 'name-7', index: 0, }, ]; console.log(list.map(item => item.name)); const sortedList = list.sort((a, b) => a.index - b.index) console.log(sortedList.map(item => item.name));
И тогда мы можем запустить приложение с помощью командной строки
yarn run android
or
yarn run ios
на двух платформах.
И мы должны увидеть журнал входного массива и отсортированного массива в терминале, на котором работает сервер метро, например
LOG ["name-1", "name-2", "name-3", "name-4", "name-5", "name-6", "name-7"] LOG ["name-2", "name-4", "name-5", "name-6", "name-7", "name-3", "name-1"]
Таким образом, очевидно, что он стабилен, потому что порядок name-2
, name-4
, name-5
, name-6
, name-7
сохраняется.
Но это также сказало
Начиная с версии 10 (или EcmaScript 2019), спецификация требует, чтобы
Array.prototype.sort
был стабильным. До версии 10 (или EcmaScript 2019) стабильность сортировки не гарантировалась — https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Но стабилен ли он на старых версиях React Native? Давайте проверим это.
Во-первых, мы можем проверить версию React Native из package.json
, затем мы можем найти версию React Native этого проекта 0.69.4, последняя версия на данный момент.
Давайте создадим еще один проект с более старой версией React Native, например 0.64. Мы можем запустить следующую команду, чтобы создать проект с определенной версией React Native.
npx react-native init sorting --template [email protected]
Мы можем найти таблицу по адресу https://www.npmjs.com/package/react-native-template-typescript
А затем мы создадим приложение с той же модификацией и запустим его, мы обнаружим, что функция сортировки также стабильна.
Таким образом, мы можем сделать простой вывод, что функция сортировки стабильна с движком JS по умолчанию, потому что мы все знаем, что код JS работает на движке JS в React Native.
А как насчет другого движка JS, например Hermes. Мы все знаем, что двигатель Hermes имеет лучшую производительность, но с некоторыми затратами.
Хорошо. Включите движок Hermes как https://reactnative.dev/docs/hermes.
И снова пересоберите и запустите приложение, мы обнаружим, что оно напечатано
LOG ["name-1", "name-2", "name-3", "name-4", "name-5", "name-6", "name-7"] LOG ["name-4", "name-5", "name-6", "name-7", "name-2", "name-3", "name-1"]
Порядок элементов с одинаковым ключом сортировки меняется. Это не стабильная сортировка.
Так что это очевидная проблема с двигателем Hermes.
Как насчет другой версии двигателя Hermes. Но, к сожалению, версия движка Hermes связана с версией React Native как https://github.com/facebook/hermes/releases.
Поэтому нам нужно сначала обновить React Native с помощью команды
npx react-native upgrade x.xx.x
Релизные версии React Native можно найти на https://github.com/facebook/react-native/releases.
После тестирования нескольких версий мы обнаружили, что Hermes 0.11 на React Native 0.69.4 исправил эту нестабильную проблему сортировки.
Собственно, этот вопрос также рассматривается на https://github.com/facebook/hermes/issues/212.
Итак, дело закрыто.