1

次のような 2 つの配列があります。

$arr1 = ("stringType1AndSomeRandomStuff",
         "stringType2AndSomeRandomStuff",
         "stringType3AndSomeRandomStuff",
         "stringType1AndSomeRandomStuff",
         "stringType2AndSomeRandomStuff",
         "i don't belong here at all!",
         "stringType4AndSomeRandomStuff");

この最初の配列 ( $arr1) では、ほとんどのキーに何らかの共通の属性があります。上記のテキスト例では、これはstringTypeX. この「共通要因」は、私が検索する必要があるものです。各文字列には、 に例示された何らかの追加データもありますAndSomeRandomStuff

2 番目の配列は次のようになります。

$arr2 = ("stringType1" => "category1",
         "stringType2" => "category2",
         "stringType3" => "category3",
         "stringType4" => "category4");

の各文字列を調べて、 のいずれかのキー$arr1厳密に一致するかどうかを確認する必要があります。いずれかのキーに一致する場合は、からのキーのが必要です。$arr2$arr2

の各文字列を反復処理して、適用されるキー$arr1(ある場合) を判断するにはどうすればよいですか? 基本的に、最も近い一致を見つけるには、のすべての文字列を調べて、 のすべてのキーに対して部分一致を実行する必要があります。頭に浮かぶ当面の解決策は、2 つのループ ( in のすべての外側と inのそれぞれの内側) を使用することですが、PHP に、文字列を取り、それが既存の配列内の文字列と一致するかどうかを確認できる関数はありますか? これを行うためのよりパフォーマンスの高い方法を知っている人はいますか?$arr2$arr1$arr2$arr1$arr2

4

1 に答える 1

3

$arr1のキーへの string-edit-distance を計算し$arr2、最も近い一致を返す関数にマップします。このレーベンシュタイン距離関数を見てください。または、マッピング関数で単にstartsWith比較を行うこともできます。

次のようなものが表示される可能性があります。

$stringEditDistanceThreshold = 5; // greater than this means rejected

// define the mapping function
function findClosestMatchingString($s) {
    $closestDistanceThusFar = $stringEditDistanceThreshold + 1;
    $closestMatchValue      = null;

    foreach ($arr2 as $key => $value) {
        $editDistance = levenshtein($key, $s);

        // exact match
        if ($editDistance == 0) {
            return $value;

        // best match thus far, update values to compare against/return
        } elseif ($editDistance < $closestDistanceThusFar) {
            $closestDistanceThusFar = $editDistance;
            $closestMatchValue      = $value;
        }
    }

    return $closestMatch; // possible to return null if threshold hasn't been met
}

// do the mapping
$matchingValues = array_map('findClosestMatchingString', $arr1);

$stringEditDistanceThreshold満足のいく値が得られるまで、おそらく調整する必要があります。または、 startsWith関数を使用することもできます。これにより、必要な作業が大幅に簡素化findClosestMatchingStringされます。

最後に、これはあまり効率的ではありません。これは事実上、醜いネストされたループです。剪定などの巧妙な方法を実行できるかもしれませんが、配列がかなり小さい場合は気にしないかもしれません。

編集:以下のコメントで @Ohgodwhy が述べているように、preg_grepはさらにうまく機能する可能性があります。その場合、マップ関数は次のようになります。

function findFirstMatchingString($s) {
    $matchingKeys = preg_grep($s, array_keys($arr2));

    if (!empty($matchingKeys) {
        // return the value of the first match
        return $arr2[$matches[0]];
    }

    return null;
}
于 2013-07-18T00:49:02.113 に答える