我有一个应该呈现随机颜色的函数,但无需重复颜色。
表示如果随机选择了蓝色,则不能再次选择它。当然,这意味着需要一个默认值。我当时在考虑使用switch
语句。
这是我当前的代码:
const colors = {
grey: '#BDC8D1',
blue: '#0500FF',
pink: '#FF00C7',
orange: '#FF7A00'
}
const randomColor = () => {
let keys = Object.keys(colors)
return colors[keys[keys.length * Math.random() << 0]]
}
答案 0 :(得分:5)
您可以“使用”一个有效值数组以返回。我的意思是从数组中删除它们。
例如:
// List of all valid values (those that can be returned)
const colors = [ 'red', 'green', 'blue' ];
// The default color (when all others have been "consumed")
const defaultColor = 'black';
// The function that returns a random color
const getRandomColor = () => {
// At least we return a color
let color = defaultColor;
// If all colors were previously consumed, we won't need
// to pick one randomly
if (colors.length > 0) {
// We select randomly an index from the colors array
const index = Math.floor(colors.length * Math.random());
// We store the color to return
color = colors[index];
// We remove it from the array
colors.splice(index, 1);
}
return color;
};
console.log(getRandomColor());
console.log(getRandomColor());
console.log(getRandomColor());
console.log(getRandomColor());
console.log(getRandomColor());
console.log(getRandomColor());
此解决方案的明显问题是您不能多次重用函数。
更好的解决方案是创建一个迭代器。每次应用程序的某些部分需要生成随机的一系列颜色时,您都会创建一个新的迭代器,并使用其next
方法来获取新值。
检查以下内容:
// The default color (when all others have been "consumed")
const defaultColor = 'black';
const RandomColorIterator = () => {
// List of all valid values (those that can be returned)
const colors = [ 'red', 'green', 'blue' ];
return {
next: () => {
// At least we return a color
let color = defaultColor;
// If all colors were previously consumed, we won't need
// to pick one randomly
if (colors.length > 0) {
// We select randomly an index from the colors array
const index = Math.floor(colors.length * Math.random());
// We store the color to return
color = colors[index];
// We remove it from the array
colors.splice(index, 1);
}
return color;
},
};
};
const iterator1 = RandomColorIterator();
console.log('1:', iterator1.next());
console.log('1:', iterator1.next());
console.log('1:', iterator1.next());
console.log('1:', iterator1.next());
console.log('1:', iterator1.next());
console.log('1:', iterator1.next());
console.log('1:', iterator1.next());
console.log('1:', iterator1.next());
console.log('1:', iterator1.next());
const iterator2 = RandomColorIterator();
console.log('2:', iterator2.next());
console.log('2:', iterator2.next());
console.log('2:', iterator2.next());
console.log('2:', iterator2.next());
console.log('2:', iterator2.next());
console.log('2:', iterator2.next());
console.log('2:', iterator2.next());
console.log('2:', iterator2.next());
我一直在使用箭头功能从父范围中获利。这样可以在每次通话的基础上访问colors
。
答案 1 :(得分:1)
只是有所不同,并使用一些函数式编程:
const colors = {
grey: '#BDC8D1',
blue: '#0500FF',
pink: '#FF00C7',
orange: '#FF7A00'
}
const randomIndex = arr => (Math.random() * arr.length) >> 0
const getColors = (keys = [], times = 0, colors = []) => {
if (!keys.length || times <= 0) {
return colors
}
const randIndex = randomIndex(keys)
colors.push(keys[randIndex])
keys.splice(randIndex, 1)
times--
return getColors(keys, times, colors)
}
// select 2 colors
console.log(getColors(Object.keys(colors), 2))
注意:最好不要对参数keys.splice
进行突变
此外,这是别人提到的.sort
方法-好主意。
Object.keys(colors).sort((a, b) => {
const order = [ -1, 0, 1 ]
return order[(Math.random() * 3) >> 0]
})
答案 2 :(得分:0)
这是一个实际的实现:
const colors = {
grey: '#BDC8D1',
blue: '#0500FF',
pink: '#FF00C7',
orange: '#FF7A00'
}
let keysArr = Object.keys(colors);
let keyArrLength = keysArr.length
for (let i = 0; i < keyArrLength; i++) {
let el = keysArr[Math.floor(Math.random() * keysArr.length)];
console.log(el);
let index = keysArr.indexOf(el);
keysArr.splice(index, 1);
}
希望这会有所帮助,如果您有任何疑问可以发表评论;)。