Проверьте значения экземпляра того же класса в PHP - PullRequest
1 голос
/ 16 ноября 2010

У меня есть класс: Game со значениями.

У меня есть два массива с экземплярами Game.Теперь мне нужно сравнить эти два массива на одинаковые значения в экземпляре игры.

У игрового класса есть атрибуты: homeId visitId

Теперь мне нужно проверить одинаковые значения в обоих массивах (онибольшие, более 100 экземпляров игры)

Что я делаю:

foreach ($games1 as $game1) {
 foreach ($games2 as $game2) {
   if ( ($game1->getHomeId() == $game2->getHomeId()) && ($game1->getVisitingId() == $game2->getVisitingId())) {
     //Games are the same
   }
 }
}

Это занимает много времени, есть ли способ сделать это быстрее?

Ответы [ 4 ]

1 голос
/ 16 ноября 2010

Ваше текущее решение имеет сложность O (n * n). возможно уменьшить его до O (nlogn). Для этого вам нужно отсортировать оба массива, а затем сравнить их. Я бы сделал что-то вроде:

$t1=array();
foreach ($games1 as $key=>$game1) {
  $t1[$key]=$game1->getHomeId;
}
asort($t1);
$t2=array();
foreach ($games2 as $key=>$game2) {
  $t2[$key]=$game2->getHomeId();
}
asort($t2);
$el1=each($t1);
$el2=each($t2);
do{
  if ($el1['value']<$el2['value'])
    $el1=each($t1);
  elseif ($el1['value']>$el2['value'])
    $el2=each($t2);
  elseif($games1[$el1['key']]->getVisitingId == $games2[$el2['key']]->getVisitingId())
    //game are the same

}while($el1 !== false && $el2 !== false)

это приводит к значительным накладным расходам, поэтому при небольшом объеме данных он будет работать медленнее. Однако чем больше данных в массивах, тем эффективнее будет этот алгоритм.

0 голосов
/ 16 ноября 2010

У меня это работает, но оно грязное, я думаю.

Сначала я сохраняю экземпляры в хеш-таблице, хеш создается из visitorId и homeId.

Затем я создаю хэш visitorId и homeId массива других игр.

Затем я извлекаю экземпляр, используя $ table [$ hash].

Массивы, которые я имел, не одинаковы по длине, так что это работает. Я не знаю, если это слишком грязно, чтобы размещать здесь, но это работает: P

foreach($pGames as $pGame) {
    $hash = $pGame->getHomeId() . '-' . $pGame->getVisitingId();
        $table[$hash] = $pGame; 
}
foreach($games as $game) {
    $hash = $game->getHomeId() . '-' . $game->getVisitingId();
    $pGame = $table[$hash];
    if($pGame instanceof Game) {
        //use the instance
    }
}
0 голосов
/ 16 ноября 2010

Как насчет использования функции array_diff, которая сравнивает два массива. http://php.net/manual/en/function.array-diff.php

0 голосов
/ 16 ноября 2010

Вы делаете много лишних вычислений.Используйте петлю for вместо петли foreach и начинайте с того места, где вы остановились, а не с начала:

$games1_count = count($games1);
$games2_count = count($games2);

for($i=0; $i < $games1_count; $i++) {
    $game1 = $games1[$i];
    for($j=$i; $j < $games2_count; $j++) {
        $game2 = $games2[$j];
        if (($game1->getHomeId == $game2->getHomeId()) && $game1->getVisitingId == $game2->getVisitingId()) {
            //Games are the same
        }
    }
}

Это должно обеспечить довольно значительное повышение скорости.Это не уменьшит порядок проблемы, но сократит ваши вычисления пополам.

РЕДАКТИРОВАТЬ

Вы также должны посмотреть на какую-то индексацию.Например, при заполнении $game1 создайте массив, в котором будут храниться игры по значению:

$game_index = array(
    "home_id"=array(
        "id1"=>$reference_to_game_with_id1,
        "id2"=>$reference_to_game_with_id2
    ),
    "visiting_id"=array(
        "id1"=>$reference_to_game_with_visiting_id1,
        "id2"=>$reference_to_game_with_visiting_id2
    )
);
...