IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Tomáš Dvořák:21.3.2018 16:12

Ahoj, mám PSČ, které potřebuji porovnat zda právě to jedno je obsaženo v množině.

např. PSČ 150 00

množina čísel:

100 00 - 199 99
370 01 - 370 21
301 00 - 328 00
400 03 - 400 20
460 01 - 460 20
500 01 - 500 12
530 01 - 530 20
533 51 - 533 54
600 10 - 647 00
700 02 - 730 01
760 01 - 760 07
770 02 - 779 00

655 02, 656 91, 658 05, 658 56, 501 01, 503 01, 503 02, 503 11, 503 21, 503 32,
503 41, 461 77, 463 02, 463 03, 463 11, 463 12, 783 01, 783 02, 783 71, 530 78,
531 41, 532 15, 532 31, 533 01, 533 31, 533 33 ,400 01, 763 02, 763 11, 763 14

V množině jsou rozsahy čísel od do, tak i jednotlivá čísla. Potřebuji nějak elegantně porovnat zda zmíněné PSČ spadá do této množiny.

Napadá mě udělat rozsahy přes if/elseif a jednotlivá čísla přes array a porovnat jedno a druhé a pokud z toho vyjde, tak ok. Obávám se, ale že to není úplně tak elegantní řešení.

Nějaké lepší řešení?

Díky

 
Odpovědět
21.3.2018 16:12
Avatar
xpoproci
Člen
Avatar
xpoproci:21.3.2018 16:41

ja presne neviem ako to v PHP funguje ale urobil by som to tak, že by som si z rozsahov urobil slovník, kde kľúč by bol dolná hranica a hodnota by bola vrchná hranica, prešiel by som to binárnym vyhľadávaním nejako takto, je to skôr pseudokód ale

binSearch(Dict, val):
        lo = 1, hi = size(Dict)
        while lo <= hi:
                mid = lo + (hi-lo)/2
                if Dict[mid].key <= val && Dict[mid].value >= val
                        return true
                else if Dict[mid].key < target
                        lo = mid+1
                else
                        hi = mid-1
        return false

a to isté by som urobil aj s tou množinou čísel. takto by som ju prešiel s tým, že by som porovnával priamo čísla, čiže namiesto

//namiesto tohoto
if Dict[mid].key <= val && Dict[mid].value >= val
//toto
if Dict[mid] == val

takto to hľadané číslo nájdeš, resp. nenájdeš v logaritmickom čase.

Nahoru Odpovědět
21.3.2018 16:41
Motto
Avatar
Odpovídá na Tomáš Dvořák
Marian Benčat:21.3.2018 16:42

Máš už tu množinu nějak uloženou v nějakém poli? ukaž to pole (stačí pár prvků) tak jak to v tom PHP máš...

Nahoru Odpovědět
21.3.2018 16:42
Totalitní admini..
Avatar
Odpovídá na Marian Benčat
Tomáš Dvořák:21.3.2018 17:30

V poli to nemám, zatím. Nicméně do pole to asi nemám problém dát. Jedná se o ty čísla, které jsem napsal.

 
Nahoru Odpovědět
21.3.2018 17:30
Avatar
xpoproci
Člen
Avatar
xpoproci:21.3.2018 18:22
$rozsah = array(
  10000 => 19999,
  37001 => 37021,
  30100 => 32800,
  40003 => 40020,
  46001 => 46020,
  50001 => 50012,
  53001 => 53020,
  53351 => 53354,
  60010 => 64700,
  70002 => 73001,
  76001 => 76007,
  77002 => 77900
);

$cisla = array(
  65502, 65691, 65805, 65856, 50101, 50301, 50302, 50311, 50321, 50332,
  50341, 46177, 46302, 46303, 46311, 46312, 78301, 78302, 78371, 53078,
  53141, 53215, 53231, 53301, 53331, 53333 ,40001, 76302, 76311, 76314
);
sort($cisla);

$tmp1 = bin_search_dict($rozsah, 15000); //slovnik rozsahov

$tmp2 = bin_search($cisla, 53334); //zoznam cisel

function bin_search_dict($array, $value){
  $keys = array_keys($array);
  $hi = count($array);
  $lo = 0;

  while($lo<=$hi){
      $mid = floor($lo + ($hi-$lo)/2);
      if($keys[$mid]<=$value && $array[$keys[$mid]]>=$value){
            return true;
      }elseif($keys[$mid]<$value){
            $lo = $mid+1;
      }else{
            $hi = $mid-1;
      }
  }
  return false;
}

function bin_search($array, $value){
  $hi = count($array);
  $lo = 0;

  while($lo<=$hi){
      $mid = floor($lo + ($hi-$lo)/2);
      if($array[$mid]==$value){
            return true;
      }elseif($array[$mid]<$value){
            $lo = $mid+1;
      }else{
            $hi = $mid-1;
      }
  }
  return false;
}

zabudol som podotknúť, že na to aby to fungovalo to musí byť zoradené vzostupne.

Editováno 21.3.2018 18:23
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
21.3.2018 18:22
Motto
Avatar
Odpovídá na xpoproci
Tomáš Dvořák:21.3.2018 18:26

U rozsahu jsem to chtěl řešit podobně, tedy postupně procházet jednotlivé rozsahy. Co se týká těch daných čísel, nestačilo by použit funkci in_array?

 
Nahoru Odpovědět
21.3.2018 18:26
Avatar
xpoproci
Člen
Avatar
Odpovídá na Tomáš Dvořák
xpoproci:21.3.2018 18:40

Ak je ten list nezoradený tak je in_array lepšia varianta, ak zoradený je tak toto je rýchlejšie.

Nahoru Odpovědět
21.3.2018 18:40
Motto
Avatar
Tomáš Dvořák:22.3.2018 11:08

Když to udělám takto, je na tom něco špatnýho? Přijde mi kód výše zbytečně složitý.

$psc_vecer_pole = array('10000-19999','37001-37021','30100-32800','40003-40020','46001-46020','50001-50012','53001-53020','53351-53354','60010-64700','70002-73001','76001-76007','77002-77900');
$psc_vecer_pole2 = array('65502','65691','65805','65856','50101','50301','50302','50311','50321','50332','50341','46177','46302','46303','46311','46312','78301','78302','78371','53078','53141','53215','53231','53301','53331','53333','40001','76302','76311,76314');

$vecerni_psc_1 = 0;
for($i=0;$i<count($psc_vecer_pole);$i++){
    $vecerni_psc = explode("-", $psc_vecer_pole[$i]);
    if($psc>=$vecerni_psc[0] and $psc<=$vecerni_psc[1]){
        $vecerni_psc_1 = 1;
    }
}
if($vecerni_psc_1 == 0 and in_array($psc, $psc_vecer_pole2)){
    $vecerni_psc_1 = 1;
}
echo $vecerni_psc_1;
 
Nahoru Odpovědět
22.3.2018 11:08
Avatar
xpoproci
Člen
Avatar
Odpovídá na Tomáš Dvořák
xpoproci:22.3.2018 12:23

myslím, že pre toto množstvo dát je to úplne v poriadku.

Nahoru Odpovědět
22.3.2018 12:23
Motto
Avatar
xpoproci
Člen
Avatar
Odpovídá na Tomáš Dvořák
xpoproci:22.3.2018 12:32

Akurát by som breakol ten for cyklus v ife kde nastavuješ $vecerni_psc1, lebo takto zbytočne prechádzaš celý zoznam.

Nahoru Odpovědět
22.3.2018 12:32
Motto
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.