Autor Zpráva
hal_sk
Profil
Zdravím,
potrebujem vygenerovať unikátny alfanumerický string o dĺžke 5 znakov. Viem to urobiť tak, že vygenerujem každý znak tohto stringu osobitne, zapíšem ho do DB a pri ďalšom generovaní stringu, budem vždy hladať duplicity v DB a ak sa nájde, generujem znova a ak sa nenájde, tak string vyhovuje. Toto riešenie pomocou porovnávania so stringami v DB sa mi nezdá dobré, lebo niekedy sa môže stať, že v DB už bude veľa údajov a pri generovaní nového stringu a následnom hľadaní jeho duplicity v DB bude toto hľadanie veľmi náročné na HW.
Existuje na toto nejaké používané štandardné riešenie, alebo to čo som napísal stačí?

Plánujem spraviť podobnú službu ako napr: http://tiny.cc ktorá z hocijakého URL spraví napr: http://tiny.cc/wav46 (takže potrebujem vygenerovať ten string na konci alternatívnej adresy).
TomášK
Profil
hal_sk:
Stačí vždy generovat řetězec "o 1 větší": aaaaa, aaaab, ..., 99999. Pak se stačí podívat na poslední vygenerovaný řetězec a z něj odvodit další v pořadí, není nutné prohledávat celou databázi.
DoubleThink
Profil *
hal_sk:
Plánujem spraviť podobnú službu ako napr: http://tiny.cc
Aaa, další zbytečná služba.

Vzhledem k tomu, že délka řetězce je zde kritická veličina, náhodné generování, jak správně předpokládáš, bude postupně hodně kolizní. Deterministický řetězec, jak jej navrhuje TomášK je vhodným řešením, ale posloupnost by neměla jít tak snadno odhalit.
Takže bych třeba převedl číselné ID z databáze na 62kové číslo a jeho znaky nějakým (vždy stejným) způsobem zamíchal.
hal_sk
Profil
TomášK:
Jo, ale všetky služby na tvorbu alternatívnych URL čo som videl to majú bez takejto postupnosti. Asi aby ľudí nelákalo hrať sa a pozmeňovať URL. A navyše niekedy budem možno potrebovať využiť tieto unikátne stringy ako súčasť aktivačných linkov zasielaných mailom po registrácii. Tam by uhádnuteľnosť bola nebezpečná.
hal_sk
Profil
DoubleThink:
Aaa, další zbytečná služba.
Takýchto služieb je plno, ale ja sa aspoň niečo naučím a vyskúšam si to.

K ostatnému:
To znie dobre. Napíšeš mi nejaké vodítko k tomu 62kovému číslu, aby som si o tom niečo našiel? Neviem o čo ide, ale konverzia číselného ID na znaky je asi dobrý nápad.
DoubleThink
Profil *
hal_sk:
Napíšeš mi nejaké vodítko k tomu 62kovému číslu
0-9a-zA-Z
Jak se převádí číselné soustavy si nastuduj třeba na wiki.
joe
Profil
DoubleThink:
Taky nějak nejsem v obraze. Co myslíš tím 62kovým číslem? To je jaká soustava? :) Tím myslíš to "0-9a-zA-Z"?
DoubleThink
Profil *
joe:
Co myslíš tím 62kovým číslem? To je jaká soustava?
Metrákový pytel cementu, kolik váží?
joe
Profil
DoubleThink:
Váží metrák, ale nechápu spojitost.
TomášK
Profil
Naznačuje, že 62-kové číslo je číslo v 62-ové soustavě, tedy otázka nedává moc smysl. Nemají-li být čísla uhádnutelná, pak bych je generoval náhodně a ověřoval, že jsou unikátní, jinak se nejde spolehnout na to, že někdo neodhalí algoritmus. Pokud bude nad sloupcem index, bude to i docela rychlé. Pokud by ti stačilo, aby to nebylo odhalitelné na první pohled, můžeš si zkonstruovat cyklickou grupu (třeba 1..prvočíslo), vzít nějaký její generátor a přičítat/násobit generátorem. Jak se hledá generátor už si nepamatuju, ale myslím, že to jde efektivně.
Colek
Profil *
Osobně bych generoval hash URL a vzal z něj jenom posledních pár znaků. Duplicitu je samozřejmě nutno před vložením do DB ověřit.
hal_sk
Profil
Dík všetkým. Asi použijem php funkciu base64_encode s tým, že nahradím znak "/" za napr. "-" (ostatné znaky base64_encode sú url friendly) a takisto aj znaky navzájom nejako pomiešam, pola rovnakého kľúča.
1Pupik1989
Profil
Nebo napsat string se všemi znaky a pak 6x vybrat náhodné číslo či písmeno.
Ukázka
hal_sk
Profil
Nakoniec som spravil to spravil pomocou tej 62-kovej číselnej sústavy (DoubleThink), pričom som znaky pomiešal a ešte zamením ich poradie.
Teraz bude napríklad napr ID-čko: 58402846 ekvivalentné reťazcu: Zz3oL.
Keď už som sa s tým hral, spravil som funkciu ktorá konvertuje čísla desiatkovej sústavy na čísla inej ľubovoľnej sústavy, definovanej počtom hodnôt (reprezentujúcich znaky cieľovej sústavy) v poli $chars:
function ns10toX($dec_val)
{
 $result_chars = "";
 $division = 1;
 //$chars = array("|"); //jednotkova sustava
 //$chars = array("0","1"); // dvojkova
 $chars = array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"); // sestnastkova, atd
 $ns = count($chars);
 $i=0;
 
 // ak sa jedna o jednotkovu sustavu
 if($ns==1)
 {
  for($i=0;$i<$dec_val;$i++)
  {
   $result_chars.=$chars[0];
  }
  return $result_chars;
 }
 //
 
 while($division!=0)
 {
  $dec_val = $i==0 ? $dec_val : $division;
  $division = floor($dec_val/$ns);
  $remainder = $dec_val%$ns;
  $result_chars[$i] = $chars[$remainder];

  $i++;
 }

 $result_chars = strrev(implode("",$result_chars));
 return $result_chars;
}
testik
Profil *
Co třeba toto?
joe
Profil
A na tohle jste někdo narazil při hledání? Moc jsem to nezkoumal...
hal_sk
Profil
joe:
To vyzerá dobre. Ale tiež som to ešte neskúmal, ani sa mi nechce, lebo to bude určite lepšie než to moje riešenie a budem to musieť ukradnúť :-)
Joker
Profil
hal_sk:
To není třeba krást, je to pod BSD licencí, takže to jde použít i v aplikaci která není open-source (jen případné změny v té funkci musejí být open-source)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: