Сравняване на два низа, ограничени чрез bitmask в PHP

В някои PHP трябва да сравня два низа, но само върху битовете, които са зададени като един в битовата маска. Как бих приложил подобно поведение?

Опитах:

$string1='aaabbb';
$string2='ababbb';
$bitmask='101101';
function compare($string1, $string2, $bitmask){
    $resultBitmask=(~($string1 ^ $string2)|~$bitmask);
} 

За по-голяма яснота записах ff байта като 1 в битовата маска с илюстративна цел. Те всъщност биха били ff в шестнадесетичен, когато се генерира битова маска. Същото важи и за 0 като нулеви байтове.

Низът и битовата маска винаги са с различна дължина при всяко извикване на функцията. Успях да получа набор от битове за сравнение, но не мога да проверя дали всички са настроени, тъй като обективите се различават. Понастоящем използвам preg_match с регулярен израз, който съответства на произволен брой ff байта, но има ли по-елегантно решение?

Редактиране: Тъй като низовете са с произволна дължина до 4096 бита, те не могат да бъдат преобразувани в числа.


person nanofarad    schedule 24.10.2012    source източник
comment
Мисля, че ще трябва да ги конвертирате в числа.   -  person jarchuleta    schedule 25.10.2012
comment
@jarchuleta Бих, но те могат да бъдат до 4 KB.   -  person nanofarad    schedule 25.10.2012
comment
може да намерите библиотека с голям брой. или ги преобразувайте байт по време, след което сравнете.   -  person jarchuleta    schedule 25.10.2012
comment
@jarchuleta Кодът е напълно преносим към уеб хостове, които може да нямат огромни библиотеки с числа. Що се отнася до втората идея, можете ли да добавите пълен отговор относно това?   -  person nanofarad    schedule 25.10.2012


Отговори (2)


Това не е най-бързият начин да го направите, но:

$stillTheSame = true;
for($i=0;$i<=strlen($bitmask); $i++)
{
  if($bitmask[$i] == 1)
  {
    if($string1[$i] != $string2[$i]) 
    {
      $stillTheSame = false;
      break;
    }  
  }
}

Не съм сигурен за действителната ви логика на проверка, но това трябва да помогне, надяваме се.

person Martin Lyne    schedule 24.10.2012
comment
Това не е ли по-скоро обхождане, отколкото рекурсия? Но все пак трябва да работя с други разработчици и често бих предпочел да напиша нещо лесно четимо, отколкото да го обяснявам на всички всеки път, когато го погледнат. Всичко за лесен живот.. - person Martin Lyne; 25.10.2012
comment
Съжалявам, лошо ми е с терминологията. Това наистина е преминаване. - person nanofarad; 25.10.2012
comment
Това е добър отговор, но за съжаление изглежда, че отнема повече от секунда за 1000 итерации с низ от 160 байта. съжалявам - person nanofarad; 25.10.2012
comment
Не е създаден за скорост, вярно. Винаги ли е 1 битова маска за 2 низа или 1 битов код за сравняване на много низове? - person Martin Lyne; 25.10.2012
comment
Re: Последният ти коментар. Пренаписах някакъв заобикалящ код, така че една и съща битова маска се прилага за много низове, но между всяко изпълнение на хиляди низове ще се нуждае от нова битова маска и дължина. - person nanofarad; 28.10.2012
comment
Питах само, защото си помислих, че може да успеете първоначално да преминете през маската, да направите масив от strpos на всяко '1' и след това да използвате това, за да препратите директно към позициите на низ 1/2, които са необходими. Но все още не мисля, че това е точно това, което търсите. Просто потенциално ускорява бавната ми версия. Може да погледна въпроса ви отново, опитвайки се да използвам побитовия стиф, невероятно съм ръждясал с него. - person Martin Lyne; 28.10.2012
comment
Всъщност намерих решение. Вижте по-долу и благодаря за помощта! - person nanofarad; 29.10.2012

Саморешено:

Тъй като това ще се повтори с много низове с еднаква дължина по време на изпълнение, но имат различни дължини между изпълненията, трябва да проверя дали резултантният низ след побитовите операции е всички единици и правилната дължина. Разбрах, че този низ, пълен с единици, може да бъде генериран, когато е необходимо, което е доста рядко, веднъж на около 1000 сравнения на низове. Мога да генерирам низа преди изпълнение, както следва:

$ones=str_repeat(chr(255), $byte_length);

и след това дефиниране на функцията compare( малко по-различно:

function compare($string1, $string2, $bitmask){
    global $ones;
    $resultBitmask=(~($string1 ^ $string2)|~$bitmask);
    if ($resultBitmask=$ones){
         return 1;
    } else {return 0};
} 

Номерът беше str_repeat, за което не знаех преди.

person nanofarad    schedule 28.10.2012