Passed
Pull Request — master (#10)
by Akpé Aurelle Emmanuel Moïse
02:03
created

jaroWinklerDistance::prepareJaroWinkler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 12
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
/**
4
*
5
* @Name : similar-text
6
* @Programmer : Akpé Aurelle Emmanuel Moïse Zinsou
7
* @Date : 2019-04-01
8
* @Released under : https://github.com/manuwhat/similar-text/blob/master/LICENSE
9
* @Repository : https://github.com/manuwhat/similar
10
*
11
**/
12
13
14
namespace EZAMA{
15
    class jaroWinklerDistance extends distance
16
    {
17
        public static function jaroWinkler($a, $b, $round=2)
18
        {
19
            if (!is_string($a)||!is_string($b)) {
20
                return false;
21
            }
22
            static $distance=array();
23
            static $previous=array();
24
            if (array($a,$b)===$previous) {
25
                return $distance;
26
            }
27
            $previous=array($a,$b);
28
            return self::getJWDistance($a, $b, $distance, $round);
29
        }
30
        
31
        
32
        
33
        private static function getJWDistance(&$a, &$b, &$distance, $round)
34
        {
35
            extract(self::prepareJaroWinkler($a, $b));
36
            for ($i=0,$min=min(count((array)$a), count((array)$b)),$t=0;$i<$min;$i++) {
37
                if ($a[$i]!==$b[$i]) {
38
                    $t++;
39
                }
40
            }
41
            $t/=2;
42
            $distance['jaro']=1/3*($corresponding/$ca+$corresponding/$cb+($corresponding-$t)/$corresponding);
43
            $distance['jaro-winkler']=$distance['jaro']+(min($longCommonSubstr, 4)*0.1*(1-$distance['jaro']));
44
            $distance=array_map(function ($v) use ($round) {
45
                return round($v, $round);
46
            }, $distance);
47
            
48
            return $distance;
49
        }
50
        
51
        private static function prepareJaroWinkler(&$a, &$b)
52
        {
53
            $a=self::split($a);
54
            $b=self::split($b);
55
            $transpositions=array('a'=>array(),'b'=>array(),'corresponding'=>0,'longCommonSubstr'=>0,'ca'=>count((array)$a),'cb'=>count((array)$b));
56
            $Δ=max($transpositions['ca'], $transpositions['cb'])/2-1;
57
            self::jwMatches($a, $b, $transpositions, $Δ);
58
            ksort($transpositions['a']);
59
            ksort($transpositions['b']);
60
            $transpositions['a']=array_values($transpositions['a']);
61
            $transpositions['b']=array_values($transpositions['b']);
62
            return $transpositions;
63
        }
64
        
65
        private static function jwMatches(&$a, &$b, &$transpositions, $Δ)
66
        {
67
            foreach ($a as $ind=>$chr) {
68
                foreach ($b as $index=>$char) {
69
                    self::_jwMatches($chr, $char, $index, $ind, $transpositions, $Δ);
70
                }
71
            }
72
        }
73
        
74
        private static function _jwMatches($chr, $char, $index, $ind, &$transpositions, $Δ)
75
        {
76
            if ($chr===$char&&(abs($index-$ind)<=$Δ)) {
77
                if ($ind!==$index) {
78
                    $transpositions['a'][$ind]=$chr;
79
                    $transpositions['b'][$index]=$char;
80
                } else {
81
                    if ($ind-1<=$transpositions['longCommonSubstr']) {
82
                        $transpositions['longCommonSubstr']++;
83
                    }
84
                }
85
                $transpositions['corresponding']++;
86
            }
87
        }
88
    }
89
    
90
}
91