这似乎比你想象的要简单得多。怎么样:
function randomReplace(subject, groups, wordsOnly) {
var meta = /([.?*+^$[\]\\(){}|-])/g, all = {};
groups.forEach(function(group) {
group.forEach(function(word) { all[word] = group })
});
var r = Object.keys(all).
sort(function(x, y) { return y.length - x.length }).
map(function(x) { return x.replace(meta, "\\$&") }).
join("|");
if(wordsOnly)
r = "\\b(" + r + ")\\b";
return subject.replace(new RegExp(r, "g"), function($0) {
return all[$0][Math.floor(Math.random() * all[$0].length)]
});
}
例子:
s = randomReplace(
"You aren't a crackpot! You're a prodigy!",
[
["genius", "prodigy"],
["freak", "loony", "crackpot", "crank", "crazy"],
["You're ", "You are ", "Thou art "],
["aren't", "ain't", "are not"]
]
);
console.log(s) // You ain't a crank! Thou art a genius!
正如评论中所讨论的,扩展功能可能是这样的:
function expand(s) {
var d = [];
function product(a, b) {
var p = [];
a.map(function(x) { b.map(function(y) { p.push(x + y) })});
return p;
}
function reduce(s) {
var m;
if(s.indexOf("|") >= 0)
return [].concat.apply([], s.split("|").map(reduce));
if(m = s.match(/~(\d+)(.*)/))
return product(reduce(d[m[1]]), reduce(m[2]));
return [s];
}
function add($0, $1) { d.push($1); return '~' + (d.length - 1) }
s = s.replace(/([^()|]+)/g, add);
for(var r = /\(([^()]*)\)/g; s.match(r);)
s = s.replace(r, add);
return reduce(s);
}
例子:
z = "(He|She|It|(B|R)ob(by|)) (real|tru|sure)ly is"
console.log(expand(z))
结果:
[
"He really is",
"He truly is",
"He surely is",
"She really is",
"She truly is",
"She surely is",
"It really is",
"It truly is",
"It surely is",
"Bobby really is",
"Bobby truly is",
"Bobby surely is",
"Bob really is",
"Bob truly is",
"Bob surely is",
"Robby really is",
"Robby truly is",
"Robby surely is",
"Rob really is",
"Rob truly is",
"Rob surely is"
]