基于枚举常量的 typescript 排序

55ooxyrt  于 2023-02-05  发布在  TypeScript
关注(0)|答案(4)|浏览(107)

有没有可能让枚举列表按照这些枚举声明的顺序进行排序?

enum MyEnum {
    VALUE_1,
    VALUE_3,
    VALUE_2
}

我创建了一个随机顺序的列表

let list = [MyEnum.VALUE_3, MyEnum.VALUE_1, MyEnum.VALUE_2];

但它是在声明枚举时排序的

[MyEnum.VALUE_1, MyEnum.VALUE_3, MyEnum.VALUE_2]

PS:我真的很想知道typescript是否像Java中那样对列表进行了直接排序,而不必自己排序。如果我必须自己排序列表,如果顺序发生变化,我很容易出错。

qpgpyjmq

qpgpyjmq1#

刚才也有同样的问题。这是我的解决方案:

enum Weekday {
  MONDAY = 'MONDAY',
  TUESDAY = 'TUESDAY',
  WEDNESDAY = 'WEDNESDAY',
  THURSDAY = 'THURSDAY',
  FRIDAY = 'FRIDAY',
  SATURDAY = 'SATURDAY',
  SUNDAY = 'SUNDAY'
}

const weekdayOrder = Object.values(Weekday);

const weekdaysToBeSorted = [Weekday.TUESDAY, Weekday.MONDAY, Weekday.FRIDAY];

const sortedWeekdays = weekdaysToBeSorted
  .sort((a, b) => weekdayOrder.indexOf(a) - weekdayOrder.indexOf(b))

(打字机Playground)

zzwlnbp8

zzwlnbp82#

如果您查看枚举的已编译javascript:

var MyEnum;
(function (MyEnum) {
    MyEnum[MyEnum["VALUE_1"] = 0] = "VALUE_1";
    MyEnum[MyEnum["VALUE_3"] = 1] = "VALUE_3";
    MyEnum[MyEnum["VALUE_2"] = 2] = "VALUE_2";
})(MyEnum || (MyEnum = {}));

您将看到每个字符串都根据位置获得一个序数,因此第一个是0,最后一个是2。
如果你引用一个枚举,你只会得到一个数字:

console.log(MyEnum.VALUE_3); // 1

如果要对列表进行排序:

let list = [MyEnum.VALUE_3, MyEnum.VALUE_1, MyEnum.VALUE_2];
console.log(list); // [1, 0, 2]
list.sort((a, b) => a - b);
console.log(list); // [0, 1, 2]

如果你希望枚举的字符串名称列表按序号排序,那么你可以:

let names = list.map(ordinal => MyEnum[ordinal]);
console.log(names); // ["VALUE_1", "VALUE_3", "VALUE_2"]

(code在Playground)

编辑

无论如何设置枚举值,都可以用同样的方式进行排序,只需更改compare function
例如,这将根据枚举字符串值的字典顺序对列表进行排序:

enum MyEnum {
    VALUE_1 = "value 1" as any,
    VALUE_3 = "value 3" as any,
    VALUE_2 = "value 2" as any
}

let list = [MyEnum.VALUE_3, MyEnum.VALUE_1, MyEnum.VALUE_2];
console.log(list); // ["value 3", "value 1", "value 2"]
list.sort((a, b) => {
    if (a < b) return -1;
    if (a > b) return 1;
    return 0;
});
console.log(list); // ["value 1", "value 2", "value 3"]

let names = list.map(ordinal => MyEnum[ordinal]);
console.log(names); // ["VALUE_1", "VALUE_2", "VALUE_3"]

(code在Playground)

编辑#2

按枚举的原始顺序排序很棘手,您可以尝试:

enum MyEnum {
    VALUE_1 = "value 1" as any,
    VALUE_3 = "value 3" as any,
    VALUE_2 = "value 2" as any
}

let list = [MyEnum.VALUE_3, MyEnum.VALUE_1, MyEnum.VALUE_2];
console.log(list); // ["value 3", "value 1", "value 2"]

let sorted = [] as MyEnum[];
let index = 0;
for (let key in MyEnum) {
    if (index % 2 === 0) {
        sorted.push(key as any);
    }

    index++;
}

console.log(sorted); // ["VALUE_1", "VALUE_3", "VALUE_2"]

let names = sorted.map(ordinal => MyEnum[ordinal]);
console.log(names); // ["value 1", "value 3", "value 2"]

(code在Playground)
这似乎是可行的,但你不应该指望在for/in循环中接收到的顺序,除非你不关心跨浏览器行为(或特定的资源管理器支持),你可以在MDN中阅读它。

r1zk6ea1

r1zk6ea13#

这是另一个解决方案,即使其他参与者改变了枚举的顺序,也可以防止缺陷。

enum Action {
    EAT = 'EAT',
    PLAY = 'PLAY',
    SING = 'SING',
    SLEEP = 'SLEEP',
}

const actionOrder = {
    [Action.SING] : 1,
    [Action.PLAY] : 2,
    [Action.EAT] : 3,
    [Action.SLEEP] : 4,  
} as const;

const users = [{
    "name": "Mike",
    "action": Action.EAT
}, {
    "name": "John",
    "action": Action.SLEEP
}, {
    "name": "Harry",
    "action": Action.PLAY
}
];

users.sort((a,b) => {
    return actionOrder[a.action] - actionOrder[b.action];
});

console.log(users);
a2mppw5e

a2mppw5e4#

我发现了这一点,并在我的应用程序中进行了测试:

export enum OrderState {
    New = '正在申请',
    Acting = '正在阅读',
    Completed = '书已归还',
    Rejected = '被拒申请',
    Cancelled = '撤销申请',
    Lost = '书已遗失'
}

export namespace OrderState {
    export function sort(list: OrderState[]) {
        const sorted = [];
        for (let key of Object.keys(OrderState)) {
            const defined = OrderState[key];
            for (let item of list) {
                if (item == defined) sorted.push(item);
            }
        }

        return sorted;
    }
}

let list:OrderState[] = [OrderState.Rejected, OrderState.New, OrderState.Lost]; 
let sorted = OrderState.sort(list);
console.log(sorted);

output: ["正在申请", "被拒申请", "书已遗失"]

相关问题