2

発生したインシデントの配列があります。これらはフリーテキストで記述されているため、一部のキーワードを除いてパターンに従っていません。「強盗」、「殺人者」、「住居侵入」、「自動車事故」など。これらのキーワードはテキストのどこにあってもかまいません。これらのキーワードを見つけて、たとえばカテゴリに追加したいと思います。「強盗」。

最後に、すべてのインシデントを確認したら、次のようなカテゴリのリストを作成します。

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;
    }
    ...
}

よろしくお願いします!

4

7 に答える 7

2

実は、ここではちょっと意見が合わないでしょう。。。indexOfのような文字列関数は完全にうまく 機能すると思います。

2つの入力を受け取るJavaScriptのindexOfメソッドを使用します。

string.indexOf(value、startPos);

したがって、実行できることの1つは、単純な一時変数をカーソルとして定義することです。。。

function FindIncident(phrase, word) {
    var cursor = 0;
    var wordCount = 0;
    while(phrase.indexOf(word,cursor) > -1){
        cursor = incident.indexOf(word,cursor);
        ++wordCount;        
    }
    return wordCount;
}

私はコードをテストしていませんが、うまくいけばあなたはアイデアを得るでしょう。。。

使用する場合は、開始位置に特に注意してください。

于 2013-01-09T23:50:20.410 に答える
2

次のコードは、実行できるアプローチを示しています。ここでテストできます

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;
}

「強盗」の複数形と単数形の違いだけを考慮しても、「一致」基準を満たす文字列が多数あるため、正規表現は理にかなっています。また、マッチングで大文字と小文字が区別されないようにする必要があります。

正規表現で「global」修飾子を使用して、「Murder、Murder、murder」などの文字列に一致させ、カウントを1ではなく3ずつ増やす必要があります。

これにより、一致基準とインシデントカウンターの関係を維持できます。また、グローバルカウンターの必要性を回避します(ここでは、付与INCIDENT_MATCHESされたのはグローバル変数ですが、他の場所に簡単に配置して、グローバルスコープから外すことができます。

于 2013-01-09T23:56:25.687 に答える
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++;
        }
    }
}
于 2013-01-09T23:49:03.437 に答える
1

RegExは私の頭も傷つけます。;)完全一致を探していて、タイプミスやスペルミスが気にならない場合は、インシデント文字列で、探しているキーワードを含む部分文字列を検索します。

incident = incident.toLowerCase();
if incident.search("car accident") > 0 {
    trafficAccidents += 1;
}
else if incident.search("robbery") > 0 {
    robberies += 1;
}
...
于 2013-01-09T23:54:13.717 に答える
1

オブジェクトの配列を使用して、検索している多くの異なるカテゴリをすべて格納し、適切な正規表現とカウントメンバーを備えており、すべてを4行で記述できます。

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++;

これで、必要なものに関係なく、コードの1つのセクションを編集するだけで、コード全体に伝播されます。

このコードには、各インシデントを複数のカテゴリに分類する可能性があります。これを防ぐには、ifブロックに「break」ステートメントを追加するだけです。

于 2013-01-09T23:58:29.897 に答える
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 }

これはより迅速なプロトタイプですが、複数形と複数形のキーワードで改善できる可能性があります。

デモ: http: //jsbin.com/idesoc/1/edit

于 2013-01-10T00:05:06.440 に答える
1

はい、それはそれを行う1つの方法ですが、プレーンワードを正規表現と一致させるのは少しやり過ぎです。この場合、rbtLongが提案したようにindexOfを使用する必要があります。

次の方法でさらに洗練されたものにすることができます。

  • フラグを追加しiます(小文字と大文字を一致させます)。
  • 表現に可能な単語のバリエーションを追加します。robberyに翻訳できるrobber(y|ies)ため、単語の単数形と複数形の両方に一致します。car accidentである可能性があります(car|truck|vehicle|traffic) accident

単語の境界\b

これは使用しないでください。一致する単語を英数字以外の文字で囲む必要があり、タイプミスの一致を防ぎます。クエリはできるだけ簡潔にする必要があります。


if (incident.match(/(car|truck|vehicle|traffic) accident/i)) {
    trafficAccidents += 1;
}
else if (incident.match(/robber(y|ies)/i)) {
    robberies += 1;
}

gフラグを破棄したことに注意してください。これは「グローバル一致」の略で、パーサーは最初の一致後も文字列の検索を続行します。確認された1回の発生で十分であるため、これは不要のようです。

このWebサイトは、正規表現の優れた紹介を提供します

http://www.regular-expressions.info/tutorial.html

于 2013-01-10T00:21:46.607 に答える