Reputation: 769
I'm trying to get away from using horrible switch cases in node.js. I am looking for a more efficient way of testing an input against various regex cases. Dependent on the case that is matched I either fire an event or I do some transformation of the input before running another function.
To save having a really long block of code I have cut down my function to the skeleton below so it shows a focus on the switch.
I've taken a look at the possibility of using .map to return a true false but I'm unsure how best to implement that also.
Any advise or suggestions on the best way to do this?
function ParseLogMessages(message, config, callback){
var _this = this;
try {
//Define regex in order to match strings based on case
_this.to_group = new RegExp("^\\[\\d{2}:\\d{2}\\]\\s+\\w+\\s+tg+\\s\\>{3}");
_this.from_group=new RegExp("^\\[\\d\\d:\\d\\d\\]\\s\\w+\\s\\w+\\s\\>{3}");
_this.to_person = new RegExp("^\\[\\d{2}:\\d{2}\\]\\s[a-zA-Z0-9 \\- _]+\\s\\<{3}.+");
_this.from_person = new RegExp("^\\[\\d{2}:\\d{2}\\]\\s\\w+\\s\\>{3}");
_this.contact = new RegExp("(User #+\\d+:)");
_this.contact = new RegExp("(User #+\\d+:)");
//Test message against each to find type
switch (true){
//Message sent to a group chat
case _this.to_group.test(_this.payload.raw):
break;
//Message from a group chat
case _this.from_group.test(_this.payload.raw):
break;
//Message sent to a person from the bot
case _this.to_person.test(_this.payload.raw):
break;
//Message sent from a person to the bot
case _this.from_person.test(_this.payload.raw):
break;
//Contact shared
case _this.contact.test(_this.payload.raw):
break;
default:
break;
}
callback(null,"Logfile message parsed ok!");
} catch(err) {
log.error(err);
return callback(err,null);
}
}
Upvotes: 2
Views: 159
Reputation: 234847
You can create an array of regex/function pairs and loop through the array:
_this.tests = [
{ regex: new RegExp("^\\[\\d{2}:\\d{2}\\]\\s+\\w+\\s+tg+\\s\\>{3}"), // to_group
action: ... // action for to_group
},
{ regex : new RegExp("^\\[\\d\\d:\\d\\d\\]\\s\\w+\\s\\w+\\s\\>{3}"), // from_group
action: ... // action for from_group
},
// etc.
];
Then you can loop through the array, testing, and breaking when the test works:
for (i=0; i<tests.length; ++i) {
if (tests[i].regex.test(_this.payload.raw) {
tests[i].action();
break;
}
}
Upvotes: 5
Reputation: 2244
What you want is to convert that into an associative array and match with a loop. Untested code that should work:
let patterns = {
"^\\[\\d{2}:\\d{2}\\]\\s+\\w+\\s+tg+\\s\\>{3}": funcToGroup /* code for this case, preferably a [reference to a] function object without the parens */,
"^\\[\\d\\d:\\d\\d\\]\\s\\w+\\s\\w+\\s\\>{3}": function () {
// An inline anonymous function is also fine
},
"^\\[\\d{2}:\\d{2}\\]\\s[a-zA-Z0-9 \\- _]+\\s\\<{3}.+": funcToPerson,
"^\\[\\d{2}:\\d{2}\\]\\s\\w+\\s\\>{3}": funcFromPerson,
"(User #+\\d+:)": funcContactShared
};
for (let pat in _this.patterns) {
if (new RegExp(pat).test(_this.payload.raw)) {
_this.patterns[pat](); // Actually execute the relevant case
}
}
That should handle all the code within the try
block.
Upvotes: 0
Reputation: 700562
You can put the objects in an array and call the test function until one returns true:
var o = [
_this.to_group,
_this.from_group,
_this.to_person,
_this.from_person,
_this.contact
];
for (var i in o) {
if (o[i].test(_this.payload.raw)) {
// got a match
break;
}
}
Upvotes: 2