我有一个已发生事件的数组,这些事件是用自由文本编写的,因此除了某些关键字之外没有遵循模式,例如。 “抢劫”,“凶手”,“入室盗窃”,“车祸”等。这些关键字可以在文本中的任何位置,我想找到这些关键字并将其添加到类别中,例如。 “抢劫”。
最后,当我检查了所有事件时,我想要一个这样的类别列表:
Robberies: 14
Murder attempts: 2
Car accidents: 5
...
数组元素如下所示:
incidents[0] = "There was a robbery on Amest Ave last night...";
incidents[1] = "There has been a report of a murder attempt...";
incidents[2] = "Last night there was a housebreaking in...";
...
我想这里最好的是使用正则表达式来查找文本中的关键字,但我真的很喜欢regexp,因此需要一些帮助。
下面的正则表达式不正确,但我猜这个结构会起作用吗? 有没有更好的方法来避免DRY?
var trafficAccidents = 0,
robberies = 0,
...
function FindIncident(incident) {
if (incident.match(/car accident/g)) {
trafficAccidents += 1;
}
else if (incident.match(/robbery/g)) {
robberies += 1;
}
...
}
提前多多感谢!
答案 0 :(得分:2)
实际上,我在这里不同意你的观点。 。 。我认为像indexOf
这样的字符串函数可以完美地运行。
我会使用JavaScript的indexOf方法,该方法需要2个输入:
string.indexOf(值,startPos);
因此,您可以做的一件事是将一个简单的临时变量定义为光标。 。
function FindIncident(phrase, word) {
var cursor = 0;
var wordCount = 0;
while(phrase.indexOf(word,cursor) > -1){
cursor = incident.indexOf(word,cursor);
++wordCount;
}
return wordCount;
}
我没有测试过代码,但希望你能得到这个想法。 。
如果您使用它,请特别注意起始位置。
答案 1 :(得分:2)
以下代码显示了您可以采取的方法。您可以对其进行测试here
var INCIDENT_MATCHES = {
trafficAccidents: /(traffic|car) accident(?:s){0,1}/ig,
robberies: /robbery|robberies/ig,
murder: /murder(?:s){0,1}/ig
};
function FindIncidents(incidentReports) {
var incidentCounts = {};
var incidentTypes = Object.keys(INCIDENT_MATCHES);
incidentReports.forEach(function(incident) {
incidentTypes.forEach(function(type) {
if(typeof incidentCounts[type] === 'undefined') {
incidentCounts[type] = 0;
}
var matchFound = incident.match(INCIDENT_MATCHES[type]);
if(matchFound){
incidentCounts[type] += matchFound.length;
};
});
});
return incidentCounts;
}
正则表达式是有意义的,因为即使您只考虑复数和单数形式的“抢劫”中的差异,您也会有许多符合“匹配”标准的字符串。您还希望确保匹配不区分大小写。
您需要在正则表达式上使用“全局”修饰符,以便匹配“谋杀,谋杀,谋杀”等字符串,并将计数增加3而不是仅增加1。
这允许您将匹配条件和事件计数器之间的关系保持在一起。它还避免了对全局计数器的需求(授权INCIDENT_MATCHES
在这里是一个全局变量,但是您可以轻松地将其放在其他地方并将其从全局范围中删除。
答案 2 :(得分:1)
使用对象存储数据。
events = [
{ exp : /\brobbery|robberies\b/i,
// \b word boundary
// robbery singular
// | or
// robberies plural
// \b word boundary
// /i case insensitive
name : "robbery",
count: 0
},
// other objects here
]
var i = events.length;
while( i-- ) {
var j = incidents.length;
while( j-- ) {
// only checks a particular event exists in incident rather than no. of occurrences
if( events[i].exp.test( incidents[j] ) {
events[i].count++;
}
}
}
答案 3 :(得分:1)
RegEx也让我头疼。 ;)如果您正在寻找完全匹配并且不担心拼写错误和拼写错误,我会在事件字符串中搜索包含您正在寻找的关键字的子字符串。
incident = incident.toLowerCase();
if incident.search("car accident") > 0 {
trafficAccidents += 1;
}
else if incident.search("robbery") > 0 {
robberies += 1;
}
...
答案 4 :(得分:1)
使用一个对象数组来存储您正在搜索的所有不同类别,包括一个合适的正则表达式和一个count成员,您可以用四行写出整个内容。
var categories = [
{
regexp: /\brobbery\b/i
, display: "Robberies"
, count: 0
}
, {
regexp: /\bcar accidents?\b/i
, display: "Car Accidents"
, count: 0
}
, {
regexp: /\bmurder\b/i
, display: "Murders"
, count: 0
}
];
var incidents = [
"There was a robbery on Amest Ave last night..."
, "There has been a report of an murder attempt..."
, "Last night there was a housebreaking in..."
];
for(var x = 0; x<incidents.length; x++)
for(var y = 0; y<categories.length; y++)
if (incidents[x].match(categories[y].regexp))
categories[y].count++;
现在,无论您需要什么,您只需编辑一段代码,它就会传播到您的代码中。
此代码有可能对多个类别中的每个事件进行分类。为了防止这种情况,只需在if块中添加一个'break'语句。
答案 5 :(得分:1)
你可以做类似这样的事情,它将获取数组中每个项目上找到的所有单词,它将返回一个带有计数的对象:
var words = ['robbery', 'murderer', 'housebreaking', 'car accident'];
function getAllIncidents( incidents ) {
var re = new RegExp('('+ words.join('|') +')', 'i')
, result = {};
incidents.forEach(function( txt ) {
var match = ( re.exec( txt ) || [,0] )[1];
match && (result[ match ] = ++result[ match ] || 1);
});
return result;
}
console.log( getAllIncidents( incidents ) );
//^= { housebreaking: 1, car accident: 2, robbery: 1, murderer: 2 }
这更像是一个快速原型,但可以使用复数和多个关键字进行改进。
答案 6 :(得分:1)
是的,这是一种方法,虽然将普通单词与正则表达式匹配有点过分 - 在这种情况下,你应该使用indexOf as rbtLong suggested。
你可以通过以下方式进一步完善它:
i
标志(匹配小写和大写字符)。robbery
可以翻译成robber(y|ies)
,从而匹配单词的单数和复数变体。 car accident
可以是(car|truck|vehicle|traffic) accident
。不要使用它。它需要在匹配的单词周围加上非字母数字字符,以防止匹配拼写错误。你应该尽可能地提出疑问。
if (incident.match(/(car|truck|vehicle|traffic) accident/i)) {
trafficAccidents += 1;
}
else if (incident.match(/robber(y|ies)/i)) {
robberies += 1;
}
注意我是如何丢弃g
标志的;它代表“全局匹配”并使解析器在第一次匹配后继续搜索字符串。这似乎是不必要的,因为只有一个确认的事件足以满足您的需求。
本网站提供了对正则表达式的精彩介绍