Javascript сортує масив об’єктів за логічною властивістю


79

Дивіться редагування в кінці для фактичної проблеми.

Гаразд, у мене такий сценарій:

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]

Тоді, якщо я зроблю це:

a.sort(function(a,b){return !a && b});

Це дає мені таке:

[false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]

Це сорта робить сортування ... але не зовсім ... :(

Як відсортувати цей масив?

РЕДАГУВАТИ:

Якщо вам цікаво, чому я не використав просто a.sort (), це тому, що мій фактичний масив - це об’єкти, а не простий масив, подібний до того, який я опублікував. Справжній має елементи, схожі на [{xx: true}, {xx: false}, ...]


Якщо я роблю a.map (function (x) {return x? 1: 0}). Sort (function (a, b) {return a> b}); теж не працює ... Я думаю, що я, можливо, роблю щось елементарне неправильно
— PCoelho

навіщо потрібно писати власну функцію? a.sort () повинен працювати
— Хасіб Асіф,

чи є спосіб використовувати lodash
— Mina Fawzy

Відповіді:


203

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
    
    
    a.sort(function(x, y) {
        // true values first
        return (x === y)? 0 : x? -1 : 1;
        // false values first
        // return (x === y)? 0 : x? 1 : -1;
    });
    
    console.log(a);

Ви повинні повернути 0, коли a і b обидва мають однакове значення, -1, якщо a істинно, а 1 інакше.


1
Так, ви зрозуміли :) дякую! (я прийму вашу відповідь, як тільки stackoverflow дозволить мені: P)
— PCoelho

35
Ще коротше: a.sort (function (x, y) {return y - x});
— Frambot

масив, який я сортую, не такий простий, як той, який я опублікував. Перевірте мою
— редакцію

2
@JoeFrambach Чи можете ви пояснити, як це працює, або вказати мені на нитку, яка пояснює синтаксис чогось подібного?
— Адам Мойса

6
Рішення @AdamMoisa Joe працює через щось, що називається Тип примусу. По суті, движок JS помітить, що ви намагаєтесь виконати математичну операцію (віднімання) над booleanзначеннями, тому він перетвориться falseна 0і trueв 1.
— Silvestre Herrera

36

простіший спосіб:

a = [{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false},{xx:true},{xx:false}];

a.sort(function(a,b){return a.xx-b.xx});

console.log(a);

Ви можете викликати a.reverse () після сортування (), якщо хочете, щоб воно було відсортовано в інший спосіб

EDIT: відредаговано, щоб відобразити оновлене питання сортування масиву об’єктів замість масиву булевих значень.


1
@PranavNegandhi: що поганого, так це те, що я відповів на запитання до того, як редагування перевизначило його ...
— dandavis

2
Чудово, просто якщо ви хочете, щоб це було відсортовано в інший спосіб, поміняйте місцями aта bу функції сортування, замість того, щоб викликати reverse().
— Юліан

20

Щоб запобігти неявному перетворенню типів (які мови, як TypeScript, не подобаються), ви можете використовувати Number()для явного перетворення булевого значення в число:

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
a.sort(function(x, y) {
   return Number(x) - Number(y);
});
console.log(a);

Або за допомогою функцій зі стрілками:

a = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false];
a.sort((x, y) => Number(x) - Number(y));
console.log(a);


Одне застереження: ця функція порівняння сортування не працюватиме із „невизначеними” значеннями у вхідному масиві
— JabbyPanda


9

Масив не має рівних позицій, то чому б не залишити перевірку дорівнює і завжди повернути або -1, або 1. Цей підхід добре працює з TS.

a.sort(x => x ? -1 : 1)

Примітка: Мене трохи турбує, як це впливає на внутрішні елементи функції сортування, але, схоже, це робить фокус.

Якщо ви хочете здійснити зворотне сортування

a.sort(x => !x ? -1 : 1)

2

PFB рішення також працювало для мене в Typescript Angular 2,

  let a = [{aa:"1",xx:true},{aa:"10",xx:false},{aa:"2",xx:true},{aa:"11",xx:false},{aa:"3",xx:true},{aa:"12",xx:false},{aa:"4",xx:true},{aa:"13",xx:false},{aa:"5",xx:true},{aa:"14",xx:false},{aa:"6",xx:true},{aa:"15",xx:false},{aa:"7",xx:true},{aa:"16",xx:false},{aa:"8",xx:true},{aa:"17",xx:false},{aa:"9",xx:true},{aa:"18",xx:false}];

    //a.sort(function(a,b){return a.xx-b.xx});
    a.sort(function (x, y) {
        // true values first
        return (x.xx === y.xx) ? 0 : x ? -1 : 1;
        // false values first
        // return (x === y)? 0 : x? 1 : -1;
    });
    return JSON.stringify(a);

Дякуємо за об'єктно-орієнтований спосіб. це спрацювало
— Сантош

1

Досить простим рішенням для функції порівняння є перевірка, чи a < bце дає 0 або 1 при перетворенні в число. Потім ми хочемо відобразити 0 до -1 і 1 до 1. Для цього ви можете просто помножити на 2, а потім відняти 1.

data.sort(function (a, b) {
  return (a < b) * 2 - 1
}

або просто

data.sort((a, b) => (a < b) * 2 - 1)

Проблему розібрано!

Якщо якесь із ваших значень nullвважається помилковим ( null*2 === 0), і будь-яке значення, яке є undefined, стане NaN( undefined*2 === NaN), що має зробити його останнім у будь-якому напрямку сортування.


1

Я хотів подивитися, чи зможу я це зробити, не використовуючи ? :оператора, просто для розваги.

Примітка

Це працює на всіх типах даних, що сортуються (рядки, числа), а не лише на вихідних булевих значеннях. Я не впевнений, що це швидше, ніж ? :це, і це більш складне. Мені просто набридають умовні люди, тож це лише особисті переваги.

  var b = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
  .sort((a,b) => Number(a > b) * 2 - 1);

Я можу перетворити це на функцію корисності та дати їй значущу назву:

  var sortOrder = {
    asc: (a,b) => Number(a > b) * 2 - 1,
    desc: (a,b) => Number(a < b) * 2 - 1
  }

то я можу:

  var b = [false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]
  .sort(sortOrder.asc);

2
Зверніть увагу, що sortпрацює з будь-яким числом, а не лише з -1 або 1. Тому ви можете використовувати, (a, b) => Number(a > b) - 0.5щоб уникнути множення.
— Xavier Stévenne 02

0

Я отримав помилки машинопису на return (x.xx === y.xx) ? 0 : x ? -1 : 1;

Це моє рішення, коли потрібно сортувати за логічним властивістю

this.mediaList.sort( (a: MediaAutosubscriptionModel, b: MediaAutosubscriptionModel) => {
    let status1: number = a.status === StatusEnum.ACTIVE ? 1 : 0;
    let status2: number = b.status === StatusEnum.ACTIVE ? 1 : 0;
    let comparison: number = 0;
    let direction: number = this.sortDirection === SortDirectionsEnum.ASC ? -1 : 1;
    if (status1 > status2) {
        comparison = direction;
    } else if (status1 < status2) {
        comparison = -1 * direction;
    }
        return comparison;
    });
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.