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.