Търсене в китайски текстов корпус за изречения, които съдържат само определени знаци

Цел: Търсете в масив от десетки хиляди китайски изречения, за да намерите изречения, които съдържат изключително знаци от масив от „познати знаци“.

Например: Да приемем, че моят корпус се състои от следните изречения: 1) 我去中国。 2) 妳爱他。 3) 你在哪里? Аз само „знам“ или искам изречения, които съдържат изключително тези знаци: 1) 我 2) 中 3) 国 4) 你 5) 在 6) 去 7) 爱 8) 哪 9) 里. Първото изречение ще бъде върнато като резултат, защото и трите му знака са във втория ми масив. Второто изречение ще бъде отхвърлено, защото не поисках 妳 или 他. В резултат на това третото изречение ще бъде върнато. Препинателните знаци се игнорират (както и всички буквено-цифрови знаци).

Имам работещ скрипт, който прави това (по-долу). Чудя се дали това е ефективен начин или не. Ако се интересувате, моля, разгледайте и предложете промени, напишете свои собствени или дайте съвет. Събрах някои от този скрипт и проверих някои въпроси за stackoverflow, но те не обърнаха внимание на този сценарий.

<?php
$known_characters = parse_file("FILENAME") // retrieves target characters
$sentences = parse_csv("FILENAME"); // retrieves the text corpus

$number_wanted = 30; // number of sentences to attempt to retrieve

$found = array(); // stores results
$number_found = 0; // number of results
$character_known = false; // assume character is not known
$sentence_known = true; // assume sentence matches target characters

foreach ($sentences as $s) {

    // retrieves an array of the sentence
    $sentence_characters = mb_str_split($s->ttext);

    foreach ($sentence_characters as $sc) {
        // check to see if the character is alpha-numeric or punctuation
        // if so, then ignore.
        $pattern = '/[a-zA-Z0-9\s\x{3000}-\x{303F}\x{FF00}-\x{FF5A}]/u';
        if (!preg_match($pattern, $sc)) {
            foreach ($known_characters as $kc) {;
                if ($sc==$kc) {
                    // if character is known, move to next character
                    $character_known = true;
                    break;
                }
            }
        } else {
            // character is known if it is alpha-numeric or punctuation
            $character_known = true;
        }
        if (!$character_known) {
            // if character is unknown, move to next sentence
            $sentence_known = false;
            break;
        }
        $character_known = false; // reset for next iteration
    }
    if ($sentence_known) {
        // if sentence is known, add it to results array
        $found[] = $s->ttext;
        $number_found = $number_found+1;
    }
    if ($number_found==$number_wanted)
        break; // if required number of results are found, break

    $sentence_known = true; // reset for next iteration 
}
?>

person tsroten    schedule 20.04.2012    source източник


Отговори (1)


Струва ми се, че това трябва да го направи:

$pattern = '/[^a-zA-Z0-9\s\x{3000}-\x{303F}\x{FF00}-\x{FF5A}我中国你在去爱哪里]/u';
if (preg_match($pattern, $sentence) {
    // the sentence contains characters besides a-zA-Z0-9, punctuation
    // and the selected characters
} else {
    // the sentence contains only the allowed characters
}

Уверете се, че сте запазили файла с изходния код в UTF-8.

person deceze♦    schedule 20.04.2012
comment
Браво, оценявам простотата. Има ли момент, в който регулярен израз става твърде дълъг? Например, ако търся изречения, които съдържат само знаци от набор от 2000 различни знака, няма ли да го натискам? - person tsroten; 20.04.2012
comment
Технически това би трябвало да работи добре, вероятно по-добре от многократното преминаване през 2000 знака. Вероятно обаче не бихте искали да съхранявате литералния регулярен израз за това, а да го изградите динамично. - person deceze♦; 20.04.2012
comment
Страхотно, благодаря за отговора, работи чудесно. По-скоро съм нов в regex, така че съм много невеж за това на какво е способен. - person tsroten; 20.04.2012