Сортировка массива, кроме одного элемента в JavaScript

У меня есть массив, и я сортирую его, но мне нужно отсортировать все, кроме одного элемента моего массива.

Мой массив:

var Comparison = [
    {key: "None", value: "None"},
    {key:"Geographical Area", value:"Geographical_Area"},
    {key:"Forests", value:"Forests"},
    {key:"Barren Unculturable Land", value:"Barren_Unculturable_Land"},
    {key:"Land put to Non agricultural use", value:"Land_put_to_Non_agricultural_use"},
    {key:"Land Area", value:"Land_Area"},
    {key:"Water Area", value:"Water_Area"},
    {key:"Culturable Waste", value:"Culturable_Waste"},
    {key:"Permanent Pastures", value:"Permanent_Pastures"},
    {key:"Land under Tree Crops", value:"Land_under_Tree_Crops"},
    {key:"Fallow Land excl Current Fallow", value:"Fallow_Land_excl_Current_Fallow"},
    {key:"Current Fallow", value:"Current_Fallow"},
    {key:"Total Unculturable Land", value:"Total_Unculturable_Land"},
    {key:"Net Sown Area", value:"Net_Sown_Area"},
    {key:"Gross Sown Area", value:"Gross_Sown_Area"},
    {key:"Cropping Intensity", value:"Cropping_Intensity"} ];

Я сортирую этот массив, используя этот код:

var Comparison_sort = this.Comparison.sort(function (a, b) {
  if (a.key < b.key)
      return -1;
  if (a.key > b.key)
      return 1;
  return 0;
});

Это сортирует мой массив отлично, но я хочу, чтобы один из моих элементов был сверху, то есть мой элемент None должен быть сверху и сортировать все остальные элементы.

Например, я получаю этот результат:

   {key: "Barren Unculturable Land", value: "Barren_Unculturable_Land"}
   {key: "Cropping Intensity", value: "Cropping_Intensity"}
   {key: "Culturable Waste", value: "Culturable_Waste"}
    ....
   {key: "None", value: "None"}

Но я хочу получить такой результат:

   {key: "None", value: "None"}
   {key: "Barren Unculturable Land", value: "Barren_Unculturable_Land"}
   {key: "Cropping Intensity", value: "Cropping_Intensity"}
   {key: "Culturable Waste", value: "Culturable_Waste"}
    ....

Я увидел ответ, Сортировка массива в TypeScript, но я не смог использовать этот ответ для своей проблемы.

Ответ 1

var Comparison_sort = this.Comparison.sort(function (a, b) {
  if(a.key == b.key) return 0;
  if (a.key == 'None') return -1;
  if (b.key == 'None') return 1;

  if (a.key < b.key)
      return -1;
  if (a.key > b.key)
      return 1;
  return 0;
});

говорит: "Делайте обычный сортировку, за исключением того, что ключ не имеет значения, что означает, что он должен идти первым".

Ответ 2

В качестве альтернативы вы можете отфильтровать нон и отсортировать остальные элементы. Затем конкатенируйте их друг с другом в конце.

let comparison = [{key: "None", value: "None"}, {key: "Geographical Area", value: "Geographical_Area"}, {key: "Forests", value: "Forests"}, {key: "Barren Unculturable Land", value: "Barren_Unculturable_Land"}, {key: "Land put to Non agricultural use", value: "Land_put_to_Non_agricultural_use"}, {key: "Land Area", value: "Land_Area"}, {key: "Water Area", value: "Water_Area"}, {key: "Culturable Waste", value: "Culturable_Waste"}, {key: "Permanent Pastures", value: "Permanent_Pastures"}, {key: "Land under Tree Crops", value: "Land_under_Tree_Crops"}, {key: "Fallow Land excl Current Fallow", value: "Fallow_Land_excl_Current_Fallow"}, {key: "Current Fallow", value: "Current_Fallow"}, {key: "Total Unculturable Land", value: "Total_Unculturable_Land"}, {key: "Net Sown Area", value: "Net_Sown_Area"}, {key: "Gross Sown Area", value: "Gross_Sown_Area"}, {key: "Cropping Intensity", value: "Cropping_Intensity"}];

let result = comparison
             .filter(e => e.key === 'None')
             .concat(
               comparison.filter(e => e.key !== 'None')
                         .sort((a, b) => a.key.localeCompare(b.key))
             );
               
console.log(result);

Ответ 3

Не фантазия, но довольно простой способ сделать это - просто удалить специальный элемент, отсортировать массив и вставить специальный код в любой нужный вам индекс.

var Comparison = [{ key: "None", value: "None" }, { key: "Geographical Area",value: "Geographical_Area" }, { key: "Forests", value: "Forests" }, { key: "Barren Unculturable Land", value: "Barren_Unculturable_Land" }, { key: "Land put to Non agricultural use", value: "Land_put_to_Non_agricultural_use" }, { key: "Land Area", value: "Land_Area" }, { key: "Water Area", value: "Water_Area" }, { key: "Culturable Waste", value: "Culturable_Waste" }, { key: "Permanent Pastures", value: "Permanent_Pastures" }, { key: "Land under Tree Crops", value: "Land_under_Tree_Crops" }, { key: "Fallow Land excl Current Fallow", value: "Fallow_Land_excl_Current_Fallow" }, { key: "Current Fallow", value: "Current_Fallow" }, { key: "Total Unculturable Land", value: "Total_Unculturable_Land" }, { key: "Net Sown Area", value: "Net_Sown_Area" }, { key: "Gross Sown Area", value: "Gross_Sown_Area" }, { key: "Cropping Intensity", value: "Cropping_Intensity" },];

const idx = Comparison.findIndex(a => a.key === 'None');
const none = Comparison.splice(idx, 1);
Comparison.sort((a, b) => a.key.localeCompare(b.key));
Comparison.splice(0,0, none[0]);

console.log(Comparison);

Ответ 4

Возможно, будет более эффективный подход, но это должно работать:

  1. Отфильтруйте специальное значение из вашего массива.

  2. Сортируйте массив без специального значения.

  3. Вставьте специальное значение в массив.

Для хорошего рабочего примера см. @Johan Wentholt ответ !

Ответ 5

Вы можете использовать reduce для достижения желаемого результата:

var Comparison = [{key:"Geographical Area", value:"Geographical_Area"},   {key:"Forests", value:"Forests"},   {key:"Barren Unculturable Land", value:"Barren_Unculturable_Land"}, {key: "None", value: "None"},  {key:"Land put to Non agricultural use", value:"Land_put_to_Non_agricultural_use"}, {key:"Land Area", value:"Land_Area"},   {key:"Water Area", value:"Water_Area"}, {key:"Culturable Waste", value:"Culturable_Waste"}, {key:"Permanent Pastures", value:"Permanent_Pastures"}, {key:"Land under Tree Crops", value:"Land_under_Tree_Crops"},   {key:"Fallow Land excl Current Fallow", value:"Fallow_Land_excl_Current_Fallow"},   {key:"Current Fallow", value:"Current_Fallow"}, {key:"Total Unculturable Land", value:"Total_Unculturable_Land"},   {key:"Net Sown Area", value:"Net_Sown_Area"},   {key:"Gross Sown Area", value:"Gross_Sown_Area"},   {key:"Cropping Intensity", value:"Cropping_Intensity"},]

var Comparison_sort = Comparison
                      .sort((a, b) => a.key.localeCompare(b.key))
                      .reduce((acc, e) => {
                        e.key === 'None' ? acc.unshift(e) : acc.push(e);
                        return acc;
                      }, []);

console.log(Comparison_sort);

Ответ 6

Простой однострочный: если какой-либо из ключей в Array.prototype.sort сравнения Array.prototype.sort имеет значение "Нет", тогда всегда помещайте его сверху, иначе базовое сравнение ключей с String.prototype.localeCompare():

var comparison = [{key: "None", value: "None"}, {key: "Geographical Area", value: "Geographical_Area"}, {key: "Forests", value: "Forests"}, {key: "Barren Unculturable Land", value: "Barren_Unculturable_Land"}, {key: "Land put to Non agricultural use", value: "Land_put_to_Non_agricultural_use"}, {key: "Land Area", value: "Land_Area"}, {key: "Water Area", value: "Water_Area"}, {key: "Culturable Waste", value: "Culturable_Waste"}, {key: "Permanent Pastures", value: "Permanent_Pastures"}, {key: "Land under Tree Crops", value: "Land_under_Tree_Crops"}, {key: "Fallow Land excl Current Fallow", value: "Fallow_Land_excl_Current_Fallow"}, {key: "Current Fallow", value: "Current_Fallow"}, {key: "Total Unculturable Land", value: "Total_Unculturable_Land"}, {key: "Net Sown Area", value: "Net_Sown_Area"}, {key: "Gross Sown Area", value: "Gross_Sown_Area"}, {key: "Cropping Intensity", value: "Cropping_Intensity"}];

var sorted = comparison.sort((a,b) => a.key === 'None' ? -1 : b.key === 'None' ? 1 : a.key.localeCompare(b.key));

console.log(sorted);

Ответ 7

Просто добавьте чек в начале. Если это ни один объект, то переместите его на передний план, не выполняя проверки.

var Comparison_sort = this.Comparison.sort(function (a, b) {
    if (a.key == "None" && a.value == "None")
        return -1;
    if (b.key == "None" && b.value == "None")
        return 1;
    if (a.key < b.key)
            return -1;
    if (a.key > b.key)
            return 1;
    return 0;
});

Ответ 8

Функция <Array>.sort принимает обратный вызов в качестве аргумента. Этот обратный вызов будет передан двумя значениями. Задача обратного вызова состоит в том, чтобы определить, какой из них больше. Он делает это, возвращая числовое значение.

Пусть говорят, что аргументы, переданные вашему обратному вызову, называются a и b. Я выделил значения, которые ваш обратный вызов должен возвращать для каждого случая

  • a < b Меньше 0
  • a > b Больше, чем 0
  • a = b равно 0

Это легко запомнить, потому что для числовых значений вы можете использовать a - b для получения желаемого возвращаемого значения.

Теперь, несмотря на то, что большинство обратных вызовов, переданных на .sort, очень малы, можно выполнить очень сложные функции в соответствии с вашими потребностями. В этом случае,

  • Если a.key None, a < b
  • Если b.key отсутствует, b < a
  • Иначе, используйте наш текущий механизм сортировки.

Мы могли бы воспользоваться return выражением, выходящим после его вызова. Итак, пусть реализует эту функцию bullet-by-bullet.

Чтобы сделать наш код Super Good, верните "0", когда два значения равны (даже если эти два значения имеют ключи от "Нет")

Comparison.sort(function(a, b) {
  // Our extra code
  if(a.key === b.key) return 0; // Zero (a = b)
  if(a.key === "None") return -1; // Negative (a < b)
  if(b.key === "None") return 1; // Positive (b < a)

  // Old sort
  if(a.key < b.key) return -1;
  if(b.key < a.key) return 1;  
})

Гольф для этого решения

Есть способы сделать это решение короче (и, возможно, более читаемым), что важно, когда код выполняет простые задачи.

Первое, что нужно отметить, это то, что конечная строка, if(b.key < a.key) return -1 может быть сокращена для return -1; , Это связано с тем, что если a.key < b.key или b.key = a.key мы b.key = a.key на более раннюю строку.

Во-вторых, использование синтаксиса ES6 (который может быть несовместим со старыми браузерами, особенно в отношении Internet Explorer), мы можем использовать нотацию функции стрелки для обратного вызова.

function(a, b) {} могла бы стать (a, b) => {}

Третья вещь, которую следует отметить, состоит в том, что мы можем преобразовать следующий блок кода

if(a.key < b.key) return -1;
if(b.key < a.key) return 1;

в

return (b.key < a.key) - (a.key < b.key)

Это потому, что true рассматривается как 1, а false - 0 при рассмотрении вычитания. true - false - 1 - 0 - 1, false - true - 0 - 1 является -1, а 0 - 0 равно 0. Никогда не будет ситуации, когда происходит true - true.