Completed
Pull Request — master (#54)
by Christoffer
02:45 queued 40s
created

suggestionList()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 3
nop 2
dl 0
loc 22
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
namespace Digia\GraphQL\Util;
4
5
/**
6
 * @param string $input
7
 * @param array  $options
8
 * @return array
9
 */
10
function suggestionList(string $input, array $options): array
11
{
12
    $optionsByDistance = [];
13
    $oLength = count($options);
14
    $inputThreshold = strlen($input) / 2;
15
16
    /** @noinspection ForeachInvariantsInspection */
17
    for ($i = 0; $i < $oLength; $i++) {
18
        $distance = lexicalDistance($input, $options[$i]);
19
        $threshold = max($inputThreshold, strlen($options[$i]) / 2, 1);
20
        if ($distance <= $threshold) {
21
            $optionsByDistance[$options[$i]] = $distance;
22
        }
23
    }
24
25
    $result = array_keys($optionsByDistance);
26
27
    usort($result, function ($a, $b) use ($optionsByDistance) {
28
        return $optionsByDistance[$a] - $optionsByDistance[$b];
29
    });
30
31
    return $result;
32
}
33
34
/**
35
 * @param string $aStr
36
 * @param string $bStr
37
 * @return int
38
 */
39
function lexicalDistance(string $aStr, string $bStr): int
40
{
41
    if ($aStr === $bStr) {
42
        return 0;
43
    }
44
45
    $d = [];
46
    $a = strtolower($aStr);
47
    $b = strtolower($bStr);
48
    $aLength = strlen($a);
49
    $bLength = strlen($b);
50
51
    if ($a === $b) {
52
        return 1;
53
    }
54
55
    /** @noinspection ForeachInvariantsInspection */
56
    for ($i = 0; $i <= $aLength; $i++) {
57
        $d[$i] = [$i];
58
    }
59
60
    /** @noinspection ForeachInvariantsInspection */
61
    for ($j = 1; $j <= $bLength; $j++) {
62
        $d[0][$j] = $i;
63
    }
64
65
    for ($i = 1; $i <= $aLength; $i++) {
66
        for ($j = 1; $j <= $bLength; $j++) {
67
            $cost = $a[$i - 1] === $b[$j - 1] ? 0 : 1;
68
69
            $d[$i][$j] = min($d[$i - 1][$j] + 1, $d[$i][$j - 1] + 1, $d[$i - 1][$j - 1] + $cost);
70
71
            if ($i > 1 && $j > 1 && $a[$i - 1] === $b[$j - 2] && $a[$i - 2] === $b[$j - 1]) {
72
                $d[$i][$j] = min($d[$i][$j], $d[$i - 2][$j - 2] + $cost);
73
            }
74
        }
75
    }
76
77
    return $d[$aLength][$bLength];
78
}
79