1

本当に解決策を探し(私は同様のことが求められていることを知っています)、コードの考え方を「英語」で理解しようとしました。

特定の番号を指定して、配列内で最も近い番号を見つけたい。以下のコードは私がこれまでに持っているものです。

//Array of numbers
$haystack = array(1,4,67,34,12,76,6,8,45,2);

//Number which we are finding the closest
$needle = 4;

sort($haystack);

foreach($haystack as $number){
    if($number > $needle){
        $difference = array($number-$needle);
        $smallest_num = array_shift($difference);
        echo $smallest_num.", "; //Echos out 2, 4, 8, 30, 41, 63, 72,
    }
}

よろしくお願いします。

4

4 に答える 4

0

usortこれは、Haystack全体を返すために使用することを思いついた小さな関数で、Needleへの近さでソートされています。関数の後に提供した例はechoする必要があり77ます。(少しコメントが多すぎる場合は申し訳ありませんが、私のドキュメントはばかげたものであることが好きです。)

// Sorts the array by closest to given number
function Find_Closest($Haystack, $Needle)
{
    $GLOBALS['Needle'] = $Needle; // allows $Needle to be accessible inside Compare()
    // Comparison function used by usort() to determine which number is closest to the needle
    if(!function_exists('Reviews_By_Date_Published')) // Only declare function if it hasn't already been declared
    {
        function Compare($A, $B)
        {
            global $Needle;
            $DistanceB = abs($B - $Needle);
            $DistanceA = abs($A - $Needle);
            return($DistanceA - $DistanceB);
        }
    }
    usort($Haystack, 'Compare'); // Sorts the Haystack by closest to Needle, using Compare()
    return $Haystack;
}

    // Example:
    $ArrayInQuestion = array(3,4,8,3,6,77,3,5,85,1,24,3);
    $SortedArray = Find_Closest($ArrayInQuestion, 76);
    $Closest = $SortedArray[0];
    echo "Closest = $Closest";

注意してください。私の関数は、配列が実際には配列であり、他のデータ型ではないと想定しています。

于 2013-03-17T01:03:51.173 に答える
0

私が思いついた最も単純な関数 (最も近い数値に達するまで配列を分割し続け$needle、最後に 2 つを比較します。

function findClosest($needle, array $haystack) {

    sort($haystack);

    $b = 0; // bottom
    $u = count($haystack) - 1; // up

    while ($u - $b > 1) {
        $m = round(($b + $u) / 2);
        if ($haystack[$m] < $needle) $b = $m;
        else $u = $m;
    }

    $x = $haystack[$b];
    $y = $haystack[$u];
    return (($needle-$x) > ($y-$needle)) ? $y : $x;

}

配列インデックスが配列で削減される方法の例:

$needle = 7;
$array = array(2, 4, 8, 30, 41, 63, 72);

# loop: [$b..$u]

1 loop: [0..6]
2 loop: [0..3]
3 loop: [0..2]
4 loop: [1..2]

$haystack[1]これで、が のすぐ下$needleで、$haystack[2]がすぐ上にあることがわかり$needleました。次に、スクリプトは次の評価を行います。

return (7-4 > 8-7) ? 8 : 4;

正しい結果を返します: 8.

于 2013-03-15T01:32:27.673 に答える
0

二分探索は、この場合の有力な候補のようです。

それよりも少し複雑です (たとえば、 が1,5,6あり、 を探しています4。5 を見て、左半分、つまり 1 を取得します。つまり、5 の方が近いため、戻って 5 を取得する必要があります)。基本アルゴリズムとして使用できるはずです。

于 2013-03-15T01:14:55.933 に答える
-1

levenshtein 関数を使用して、PHP ドキュメントで解決策を見つけました。サンプル コードを少し変更することで、並べ替えられた配列で最も近い数値を見つけることができました。この関数は、他の同様の PHP 関数に比べて比較的高速です。

<?php
function findClosest($input = 0){
    // array of numbers to check against
    $numbers  = array(4,7,10,15,
                    1,2,666,1234);
    sort($numbers);
    // no shortest distance found, yet
    $shortest = -1;

    // loop through numbers to find the closest
    foreach ($numbers as $num) {

        // calculate the distance between the input num,
        // and the current num
        $lev = levenshtein($input, $num);

        // check for an exact match
        if ($lev == 0) {

            // closest num is this one (exact match)
            $closest = $num;
            $shortest = 0;

            // break out of the loop; we've found an exact match
            break;
        }

        // if this distance is less than the next found shortest
        // distance, OR if a next shortest num has not yet been found
        if ($lev <= $shortest || $shortest < 0) {
            // set the closest match, and shortest distance
            $closest  = $num;
            $shortest = $lev;
        }
    }
    echo "Closest number is: " . $closest;
 }
?>

これがお役に立てば幸いです、アダム。

于 2013-03-15T02:09:51.817 に答える