javascript randoms?
I have an object that looks something like
names = {
m: [
'adam',
'luke',
'mark',
'john'
],
f: [
'lucy',
'mary',
'jill',
'racheal'
],
开发者_如何学编程 l: [
'smith',
'hancock',
'williams',
'browne'
]
};
What I want to do is.
I get a string that looks like
{m} {l} is a male name, so {f} {l} is a female name, {r} {l} must me a either/or(random) gender name
And I want it to randomly be populated from the correct keys.
so you might get
luke browne is a male name, so racheal smith is a female name, mary browne must be a either/or(random) gender name
How would I go about doing this?
the function skeleton would look something like
function names(mask, callback){}
and the last line of the code would be something like callback(replaced)
You can use Math.random()
to get a random value between 0 and 1. From there you can use Math.ceil()
or Math.floor()
with multiplication to get the desired range of values.
There are two parts of JavaScript that you need to know for this question:
Math.random()
, which is the only way to generate random numbers within JavaScript. It generates a number between 0 and 1; you can get a random integer between0
andn - 1
withMath.floor(Math.random() * n)
.- Regular expressions, for getting the "template" strings out of the mask, and for performing the replacement. The expression
mask.match(/{.}/)[0]
will give you the first template string in the mask (e.g.'{m}'
in the given case).
To replace the '{m}'
in mask
with 'foo'
, you'd write
mask = mask.replace(/{m}/, 'foo');
Put all the concepts above together in a while (mask.match(/{.}/)
loop, and voila!
First, you have to match a character inside braces, you can use regular expression to do it:
/\{(\w)\}/g
Also note that your template has {r}
tag, which is not present in the object. Let's populate it ourselves:
names.r = names.m.concat(names.f);
Here, elements in names.r
are names from both names.m
and names.f
. Then you can use string.replace to replace them.
Instead of providing a substring that gets replaced, you can instead provide a function which computes the replacement string on the fly.
function replaceNames(mask, callback) {
callback(mask.replace(/\{(\w)\}/g, function(all, category) {
var arr = names[category];
return arr[Math.floor(Math.random() * arr.length)];
}));
}
You can do something like this:
function randomName(names){
var _names = [];
for(i in names) _names.push(i);
var random = Math.floor(Math.random()*_names.length);
if(random) random -= 1; // only m and f
return names[_names[random]][Math.floor(Math.random()*names[_names[random]].length)];
}
You should use two functions: the first to parse the mask, and then second to randomly choose names.
Parsing the mask is straightforward enough. A regular expression can be used to retrieve an array of all the keys. Then you can loop through these performing the replacements.
function names(mask, callback) {
var replaced = mask;
//get an array of all the keys (with braces)
var keys = mask.match(/{[mflr]}/g);
for (var i=0; i<keys.length; i++) {
//extract the "f" from "{f}"
var type = keys[i].charAt(1);
//make the replacement
replaced = replaced.replace(keys[i], getNameFromObject(type));
}
callback(replaced);
}
The role of the second function is to choose a name from the object of names, given a certain type. In the question, this object has the identifier "names". This is also the identifier of the function that parses the mask. I recommend renaming the object to something similar to "allNames" because it will avoid possible namespace conflicts and is more expressive of the nature of the object.
As suggested, Math.random() and Math.floor() are used to choose a random index of a name. You should not use Math.ceil(), as this might cause an off-by-one error, or require subtraction by one.
function getNameFromObject(type) {
if (type == 'r')
type = (Math.random() > 0.5)? 'm' : 'f';
//assuming that the object has the type of name being requested
//NOTE: "allNames" is used as the identifier of the data object
var possibleNames = allNames[type];
//assuming the arrays can't be empty
var randomIndex = Math.floor(Math.random() * possibleNames.length);
return possibleNames[randomIndex];
}
精彩评论