phpsortingbest-fit

Sort Array by amount of matches and put best fit first php


I create a tag based search and want to sort the search result according to the relevance. The best fit and the number of tags are relevant. Imagine this is the search query:

$search = ['A', 'B'];

and this the result:

$result = [
  [
    'id' => 3011,
    'tags' => ['A', 'B', 'C']
  ],
  [
    'id' => 10798,
    'tags' => ['A','C','D','E']
  ],
  [
    'id' => 92,
    'tags' => ['A']
  ],
  [
    'id' => 4237,
    'tags' => ['A', 'B']
  ]
];

I want to reorganize the whole thing as follows:

$sortResult = [
  [
    'id' => 4237,
    'tags' => ['A', 'B'] // At first place because has 2 values and the search 2, difference 0 and matched good to search
  ],
  [
    'id' => 3011,
    'tags' => ['A', 'B', 'C'] // At second place because has 3 values and the search 2, difference 1 and matched good to search
  ],
  [
    'id' => 92,
    'tags' => ['A'] // At third place because has 1 value and the search 2, difference 1
  ],
  [
    'id' => 10798,
    'tags' => ['A','C','D','E'] // Down here because has 4 values and the search 2, difference 2
  ]
];

Solution

  • Not sure if this works in all cases but it gives the desired result for your current data:

    <?php
    $search = ['A', 'B'];
    
    $result = [
    [
        'id' => 3011,
        'tags' => ['A', 'B', 'C'],
    ],
    [
        'id' => 10798,
        'tags' => ['A', 'C', 'D', 'E'],
    ],
    [
        'id' => 92,
        'tags' => ['A'],
    ],
    [
        'id' => 4237,
        'tags' => ['A', 'B'],
    ],
    ];
    
    usort($result, function ($a, $b) use ($search) {
        $simA = count(array_intersect($a['tags'], $search));
        $simB = count(array_intersect($b['tags'], $search));
        $diffA = count(array_diff($a['tags'], $search));
        $diffB = count(array_diff($b['tags'], $search));
        $absA = abs(count($a['tags']) - count($search));
        $absB = abs(count($b['tags']) - count($search));
    
        $score = 0;
    
        $score += $simB - $simA;
        $score += $diffA - $diffB;
        $score += $absA - $absB;
    
        return $score;
    });
    
    echo '<pre>';
    print_r($result);
    echo '</pre>';
    

    http://phpio.net/s/7yhb