如何从枚举中获取随机项?
enum Colors {
Red, Green, Blue
}
function getRandomColor(): Color {
// return a random Color (Red, Green, Blue) here
}
答案 0 :(得分:2)
从其他解决方案中得到了许多启发,并使用了keyof
关键字之后,这是一个泛型方法,它返回了一个类型安全的随机枚举。
function randomEnum<T>(anEnum: T): T[keyof T] {
const enumValues = Object.keys(anEnum)
.map(n => Number.parseInt(n))
.filter(n => !Number.isNaN(n)) as unknown as T[keyof T][]
const randomIndex = Math.floor(Math.random() * enumValues.length)
const randomEnumValue = enumValues[randomIndex]
return randomEnumValue;
}
像这样使用它:
interface MyEnum {X, Y, Z}
const myRandomValue = randomEnum(MyEnum)
myRandomValue
的类型为MyEnum
。
答案 1 :(得分:1)
这是我能想到的最好的,但它看起来像是一个hack,取决于TypeScript中enum
的实现,我不确定它是否保证保持不变。
给出诸如
之类的枚举enum Color { Red, Green, Blue }
如果我们console.log
,我们会得到以下输出。
{
'0': 'Red',
'1': 'Green',
'2': 'Blue',
Red: 0,
Green: 1,
Blue: 2,
}
这意味着我们可以浏览此对象的键并仅获取数值,如下所示:
const enumValues = Object.keys(Color)
.map(n => Number.parseInt(n))
.filter(n => !Number.isNaN(n))
在我们的案例中,enumValues
现在是[0, 1, 2]
。我们现在只需要随机选择其中一个。这是一个很好的函数实现,它返回一个random integer between two values,这正是我们随机选择索引所需要的。
const randomIndex = getRandomInt(0, enumValues.length)
现在我们只选择随机枚举值:
const randomEnumValue = enumValues[randomIndex]
答案 2 :(得分:1)
您可以找到以下代码来完成工作。
enum Colors {
Red, blue, pink, yellow, Orange
}
function getRandomColor(): string
{
var len = (Object.keys(Colors).length/2)-1; // returns the length
// calculate the random number
var item = (Math.floor(Math.random() * len) + 0);
return Colors[item];
}
答案 3 :(得分:1)
上面的大多数答案都返回了枚举键,但是我们真的不在乎枚举值吗?
如果您使用lodash,这实际上很简单:
_.sample(Object.values(myEnum)) as MyEnum
不幸的是,强制类型转换是必需的,因为它返回any
类型。 :(
如果您不使用lodash或希望将其用作自己的函数,则仍可以通过将@Steven Spungin的答案修改为以下内容来获得类型安全的随机枚举:
function randomEnum<T>(anEnum: T): T[keyof T] {
const enumValues = (Object.values(anEnum) as unknown) as T[keyof T][];
const randomIndex = Math.floor(Math.random() * enumValues.length);
return enumValues[randomIndex];
}
答案 4 :(得分:1)
如果您需要支持字符串或异构枚举,我可能会建议这样的函数:
const randomEnumKey = enumeration => {
const keys = Object.keys(enumeration)
.filter(k => !(Math.abs(Number.parseInt(k)) + 1));
const enumKey = keys[Math.floor(Math.random() * keys.length)];
return enumKey;
};
要获取随机值:
const randomEnumValue = enumeration => enumeration[randomEnumKey(enumeration)];
或者简单地:
MyEnum[randomEnumKey(MyEnum)]
示例:
答案 5 :(得分:0)
编辑:固定类型问题。
整理@ ShailendraSingh的回答,如果枚举定义为问题,没有任何自定义索引,那么这是一个简单的方法:
enum Color {
Red, Green, Blue
}
function getRandomColor(): Color {
var key = Math.floor(Math.random() * Object.keys(Color).length/2);
return Color[key];
}
请注意,此处的返回类型Color
(在问题中请求)实际上是枚举索引而不是颜色名称。
答案 6 :(得分:0)
这不是完美的,但是可以尝试这样的事情。
function getRandomEnum(input: object): any {
const inputTransform: { [key: string]: string } = input as { [key: string]: string };
const keysToArray = Object.keys(inputTransform);
const valuesToArray = keysToArray.map(key => inputTransform[key]);
if (!isNaN(parseInt(keysToArray[0], 10))) {
const len = keysToArray.length;
while (keysToArray.length !== len / 2) {
keysToArray.shift();
valuesToArray.shift();
}
}
const randIndex = Math.floor(keysToArray.length * Math.random());
return valuesToArray[randIndex];
}
经过测试...
enum Names {
foo,
bar,
baz,
// foo = "fooZZZ",
// bar = "barZZZ",
// baz = "bazZZZ",
}
for (let i = 0; i < 10; i += 1) {
const result = getRandomEnum(Names);
if (result === Names.foo) console.log(`${result} is foo`);
else if (result === Names.bar) console.log(`${result} is bar`);
else if (result === Names.baz) console.log(`${result} is baz`);
}
输出...
0 is foo
0 is foo
2 is baz
0 is foo
2 is baz
2 is baz
1 is bar
1 is bar
2 is baz
1 is bar
或...
bazZZZ is baz
bazZZZ is baz
bazZZZ is baz
barZZZ is bar
bazZZZ is baz
barZZZ is bar
barZZZ is bar
fooZZZ is foo
barZZZ is bar
fooZZZ is foo
答案 7 :(得分:0)
enum Colors {
Red, Green, Blue
}
let keys = Object.keys(Colors)
let real_keys = keys.slice(keys.length / 2,keys.length)
let random = real_keys[Math.floor(Math.random()*real_keys.length)]
console.log(random)
使用esnext在打字稿3.5.2上进行了测试。非常简单。
使用命名空间的奖励
enum Colors {
Red,
Green,
Blue,
}
namespace Colors {
// You need to minus the function inside your namespace
// That's why I had - 1
// Because instead of 0,1,2,red,green,blue = 6
// It will be 0,1,2,red,green,blue,Random = 7
export function Random(): any {
let length = ((Object.keys(Colors).length - 1) / 2)
return Colors[Math.floor(Math.random() * length / 2)]
}
}
console.log(Colors.Random())
答案 8 :(得分:0)
以下是在es5中对我有用的解决方案:
function getRandomEnum<T extends object>(anEnum: T): T[keyof T] {
let enumValues = Object.keys(anEnum)
.filter(key => typeof anEnum[key as keyof typeof anEnum] === 'number')
.map(key => key);
let randomIndex = Math.floor(Math.random() * enumValues.length)
return anEnum[randomIndex as keyof T];
}
答案 9 :(得分:0)
除了@sarink答案。
import _ from 'lodash';
export function getRandomValueFromEnum<E>(enumeration: { [s: string]: E } | ArrayLike<E>): E {
return _.sample(Object.values(enumeration)) as E;
}
答案 10 :(得分:0)
适用于所有类型枚举的简单解决方案
function randomEnum<T extends Record<string, number | string>>(anEnum: T): T[keyof T] {
const enumValues = getEnumValues(anEnum);
const randomIndex = Math.floor(Math.random() * enumValues.length);
return enumValues[randomIndex];
}
使用了lodash,但是没有它可以重写函数
function getEnumValues<T extends Record<string, number | string>>(anEnum: T): Array<T[keyof T]> {
const enumClone = _.clone(anEnum);
_.forEach(enumClone, (_value: number | string, key: string) => {
if (!isNaN(Number(key))) {
delete enumClone[key];
}
});
return _.values(enumClone) as Array<T[keyof T]>;
}
enum Status { active, pending }
enum Type { active = 'active', pending = 'pending' }
enum Mixed { active = 'active', pending = 1 }
randomEnum(Status) // (Return random between 0,1)
randomEnum(Type) // (Return 'active' or 'pending' string)
randomEnum(Mixed) // (Return 'active' or 1)
答案 11 :(得分:-1)
如何使用es2017中的Object.values(最近不支持IE和其他浏览器的支持)
function randEnumValue<T>(enumObj: T): T[keyof T] {
const enumValues = Object.values(enumObj);
const i = Math.floor(Math.random() * enumValues.length);
return enumValues[i];
}```