基于枚举常量的打字稿排序

时间:2016-10-17 12:07:35

标签: typescript enums

是否可以按照这些枚举声明的顺序排列枚举列表?

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:我真的想知道打字稿是否像我们在Java中那样开箱即用,而不必自己订购。如果我必须自己订购清单,如果订单有所改变,我将容易出错。

4 个答案:

答案 0 :(得分:4)

如果你查看枚举的已编译的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 in 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 in 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 in playground

这似乎有效,但您不应该依赖于for / in循环中收到的顺序,除非您不关心跨浏览器行为(或者是特定的资源管理器支持),您可以{ {3}}

答案 1 :(得分:2)

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

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

const weekdayOrder = Object.entries(Weekday).map(([key, value]) => value);

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

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

答案 2 :(得分:0)

这是另一种解决方案。即使您的代码的其他贡献者更改了枚举的顺序,这也可以防止出现缺陷。

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);

答案 3 :(得分:-1)

我发现了这个问题,并在我的应用中对其进行了测试:

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);

输出:[“正在申请”,“被拒申请”,“书已遗失”]