Autor Zpráva
Trojan
Profil *
Ahoj, udělal jsem metodu initiate, která prochází seznam souborů a vytváří některá pole. Jedno z nich je pole priorities, které má sdružovat hodnoty pro třídění souborů v dané složce. Jde o to, aby všechny soubory s podobným jménem se mimo metodu initiate zpracovávaly v jedné skupině a aby se nejdříve zpracovaly ty co mají vyšší prioritu. Budu chtít získat seznam souborů, na jehož začátku budou soubory, kterých je nejvíce; je to skupina začínající na stejný řetězec, ale končící na různé číslo. Na druhém místě se má třídit podle abecedy vzestupně.

Asi by nemělo smysl sem vkládat celou třídu, protože je moc dlouhá, takže ji osekám o některé vlastnosti, které s metodou initiate nesouvisí a o jiné metody.

class kml_get_names_class {
    private $variants;
    private $shortcuts;
    private $priorities;
    private $bfn;

    public function __construct(&$config, $name) {
    $this->c = $config;
    $this->method_name = $name;
    $this->init_new_dir = true;
    $this->list_dirs[] = array($config->path->root."/".$config->path->subdir);
    }

// Spustit pouze jednou pro každý adresář
function initiate($path,$file){
  $this->priorities = $this->variants = $this->shortcuts = array();
  $base = array(); // temp array with basic form and no digits
  foreach ($this->main->list_files[$path] as $index => $item):
    $this->bfn[$path][$item]['dcount']=0;
    $this->bfn[$path][$item]['icount']=0;
    // prevest vsechny nazvy souboru na zakladni formu 
    $this->bfn[$path][$item][0] = $this->TextConvert($basename = basename($item,'.kml'));
    // zjistit informace o cislu
    $digit_found = preg_match('/\d+/',$this->bfn[$path][$item][0],$results);
    if ($digit_found){
        $digit_found = true;
        $digit = $this->bfn[$path][$item]['digit'] = $results[0];
        if ($file == $item):
         if ((int) $digit==0) die("<b>Chyba pojmenování souboru:</b><br>Soubor $file obsahuje číslici 0, která je rezervovaná. Čísluj soubory od čísla 1.");
         elseif ((int) $digit==10) $digit = '0'; "";
        endif;
        $this->bfn[$path][$item][0]=str_replace($this->bfn[$path][$item]['digit'],'',$this->bfn[$path][$item][0]); // odstranit cislo
        }
    else 
    
    $pos=strpos($this->bfn[$path][$item][0],'(');
    if ($pos) $this->bfn[$path][$item][0]=substr($this->bfn[$path][$item][0], 0, $pos);  // odstranit poznamky a okres
    $this->bfn[$path][$item][0]=trim($this->bfn[$path][$item][0],' '); // trimovat mezery
    $base[$item]=$this->bfn[$path][$item][0];    
    $this->priorities[$path][$base[$item]]=0;
  endforeach;
  
  if ($this->bfn[$path][$item]['icount'] === $this->bfn[$path][$item]['dcount']) $this->bfn[$path][$item]['dcount']=0; // jde jen o jeden soubor, takže číslo nehraje roli

  foreach ($this->main->list_files[$path] as $index => $key):
     $this->variants[$key] = array();
     $this->shortcuts[$key] = false;
     foreach ($this->main->list_files[$path] as $i => $f):
         if ($index===0) $this->bfn[$path][$key][0] = $this->TextConvert($basename = basename($file,'.kml'));
         // potom porovnat aktualni soubor $file s ostnimi soubory
         if ($file==$f) continue;
        if ( strpos($this->bfn[$path][$f][0], $base[$item])!==false ): // pokud základní slovo je obsaženo v názvu souboru
            echo $base[$key]."<br>";
            $this->priorities[$path][$base[$key]]++;
        endif;
        
     endforeach;
  
  endforeach;
  print_r($this->priorities[$path]);
  die();
  print_r($this->bfn[$path]);
  die();

}

function kml_get_names($path, $file)
{
  list ($return, $report) = $this->main->timeController($file);
  if ( $return ) return $report;     
  
  if ( $this->init_new_dir ):
    $this->initiate($path,$basename = basename($file));
    $this->generateShortcuts($path,$basename); 
  endif;
 
return $str;
}

}
Die způsobí, že se vypíše seznam souborů pouze u prvního adresáře.

Vysvětlení:
$this->bfn[$path][$item][0] - překonvertovaný název souboru v lowercase a bez diakritiky a bez číslice
$this->bfn[$path][$item]['digit'] - číslice souboru
$this->bfn[$path][$item]['dcount'] - obsahuje názvy souborů pro daný adresář, čísla dcount, počet souborů se stejným tvarem názvu, ale s odlišnou číslicí.
$file - první soubor v prvním adresáři
$key - aktuálně zpracovávaný soubor
$base a $base[$key] - nese hodnotu $this->bfn[$path][$item][0] upravenou o odstranění čísla. Je to základní forma názvu souboru připravená na porovnávání.
$base[$key] - dynamickým způsobem přistupuji název souboru bez diakritiky. Pro zjednodušeni. Pokud se soubor jmenuje "Břeclav.txt", tak hodnota je "breclav.txt", na rozdíl od klíčů $this->main->list_files[$path], kde je diaktitika ve jménu "Břeclav.txt". A tady je kámen úrazu.
$this->priorities[$path][$base[$key]]++; - počítá kolik souborů s podobným jménem se nachází v adresáři.

První smyčka: Nejdříve probíhá příprava pole bfn a všech základních hodnot.
Druhá smyčka: Když jsou všechny soubory ve tvaru pro porovnávání, jedu podobnou smyčku znova, ale porovnám každý s každým kromě aktuálního souboru $f.

Lámu si hlavu s tím jak upravit strukturu
$this->priorities[$path] tak, abych měl v jednom poli možnost zpřístupnit položku pole pomocí názvu s diakritikou a zároveň měl uložený výsledek toho sčítání. Pravděpodobně bych měl znova vytvořit stejnou smyčku jako na začátku,
$this->priorities přejmenovat na dočasné lokální pole $priorities a připravit nové pole $this->priorities, ve kterém budou uloženy klíče $this->priorities[$path][$filename], $this->priorities[$path][$filename][0], $this->priorities[$path][$filename]['dcount'],$this->priorities[$path][$filename]['dcount'],$this->priorities[$path][$filename]['converted'], kde 'converted' klíč k prvku s tomu názvu bez diakritiky, lowercase, zkrácený o číslo.

Možná to řešení je snadné, ale mě to nějak nedochází, protože už to na mě začíná být moc složitý. Prosím o radu.
Trojan
Profil *
Koukám že mám chybu v popisu:
$this->bfn[$path][$item]['dcount'] - obsahuje počet souborů se stejným tvarem názvu, ale s odlišnou číslicí.
Borius
Profil
Trojan:
Možná by to chtělo jen útržek kódu, samozřejmě ten podstatný. A kratší dotaz, pokud možno jasně formulovaný. Jsem docela skeptický v tom, že se tím někdo bude „brodit“.
Trojan
Profil *
Stačí uložit kód jako třídu a spustit tímto způsobem:

$path="./test/";
$file="./test/Bedøichov.kml";
$this->main->list_files[$path] = Array
( "Bedøichov.kml",
    "Bedrichov",
    "Èerná Hora 1.kml",
    "Èerná Hora 2.kml",
    "Èerná Hora 3.kml",
    "Šošùvka.kml",
    "Štìchov.kml",
    "Žïárná.kml"
);

$this->initiate($path,$basename = basename($file));

nebo prostě:
$this->initiate($path,$basename = basename("Bedøichov.kml"));
[/pre]

Je vcelku jedno jaké soubory dosadíte, může to mít jakoukoliv koncovku, ale ve filtru jsem použil kml, takže místo txt použuju kml. Snad vám to pojede takhle. Podstané je pole list_files jako zdroj - seznam souborů s diakritikou, které budu porovnávat. A vám se vypíše to pole bfn a priorities.


$this->initiate($path,"Bedøichov.kml");

Když si odkomentujete ten print_r($this->bfn[$path]); tak vám vyleze něco takového:
(
    [Bedøichov.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => bedrichov
        )

    [Boøitov.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => boritov
        )

    [Brov-Jeneè.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => brtov-jenec
        )

    [Býkovice.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => bykovice
        )

    [Drnovice.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => drnovice
        )

    [Holštejn.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => holstejn
        )

    [Lysice.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => lysice
        )

    [Obora.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => obora
        )

    [Sloup.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => sloup
        )

    [Suchdol (Blansko).kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => suchdol
        )

    [Vavøinec.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => vavrinec
        )

    [Veselice.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => veselice
        )

    [újezd u Boskovic.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => ujezd u boskovic
        )

    [Èerná Hora 1.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => cerna hora
            [digit] => 1
        )

    [Èerná Hora 2.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => cerna hora
            [digit] => 2
        )

    [Èerná Hora 3.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => cerna hora
            [digit] => 3
        )

    [Šošùvka.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => sosuvka
        )

    [Štìchov.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => stechov
        )

    [Žïárná.kml] => Array
        (
            [dcount] => 0
            [icount] => 0
            [0] => zdarna
        )

No a Já potřebuju vymyslet jak změnit tuto strukturu, aby se to dalo použít pro array_multisort. To co chci získat jsou dvě pole $arg, které se použijou pro ten multisort:
bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC [, mixed $arg = SORT_REGULAR [, mixed $... ]]] )
Jedno pole má obsahovat hodnoty dcount a druhé pole má obsahovat názvy souborů.


Jenže ty hodnoty dcount mají být ty samé hodnoty jako jsou v poli $this->priorities[$path]:
(
[bedrichov] => 1
[boritov] => 1
[brtov-jenec] => 1
[bykovice] => 1
[drnovice] => 1
[holstejn] => 1
[lysice] => 1
[obora] => 1
[sloup] => 1
[suchdol] => 1
[vavrinec] => 1
[veselice] => 1
[ujezd u boskovic] => 1
[cerna hora] => 3
[sosuvka] => 1
[stechov] => 1
[zdarna] => 1
)
Problém je v tom jak dostat ty hodnoty z $this->priorities do $this->bfn[$path]
Trojan
Profil *
V podstatě jsem to vyřešil opravou těchto řádků:
         if ($key==$f) continue;
        if ( strpos($this->bfn[$path][$f][0], $base[$item])!==false ): // pokud základní slovo je obsaženo v názvu souboru
            $this->priorities[$path][$base[$key]]['count']++;
            $this->priorities[$path][$base[$key]]['files'][$key]='';
        endif;
Tedy mám teď informaci o tom kolikrát se vyskytuje soubor s podobným jménem, mám tam uloženo i které soubory to jsou. Teď ut jen projít v dalším cyklu $this->priorities[$path][$base[$key]] a vytvořit pole $arg pro uspořádání pomocí array_multisort.
_construct
Profil *
<?php
class ArrayMultiSort {
    
    public $DataArray = array();// $this->DataArray
    
    public function SortDataArray($SortByCol, $Direction, $Type){
        /*****
        Vstupné polia sa spracujú ako stĺpce tabuľky, ktorá sa má triediť podľa riadkov - toto sa podobá klauzule SQL ORDER BY. 
        Prvé pole je primárne, podľa ktorého sa zoraďuje.
        Defaultné Návestia SORT_ASC a SORT_REGULAR. 
        $Direction - Návestia smeru zoradenia: 
            SORT_ASC - zoradiť vzostupne
            SORT_DESC - zoradiť zostupne
        $Type - Návestia typov zoradenia: 
            SORT_REGULAR - porovnávať položky normálne
            SORT_NUMERIC - porovnávať položky číselné
            SORT_STRING - porovnávať položky ako reťazce
        */
        if(is_array($this->DataArray)){
            $SortCol = array();
            foreach($this->DataArray as $Row => $Line){
                $SortCol[] = $Line[$SortByCol];
            }
            return array_multisort($SortCol, $Direction, $Type, $this->DataArray);
        }
    }
}
?>
Trojan
Profil *
_construct:
Jo, to já vím jak se dělá porovnávání. Ještě jsem to trochu opravil a přidal cyklus, který připraví to hlavní pole s prioritama na třídění:

  foreach ($this->main->list_files[$path] as $index => $key):
     $this->variants[$key] = array();
     $this->shortcuts[$key] = false;
     foreach ($this->main->list_files[$path] as $i => $f):
        if ($index===0) $this->bfn[$path][$key][0] = $this->TextConvert($basename = basename($file,'.kml'));
        if ($key==$f) continue;
        if ( strpos($this->bfn[$path][$f][0], $base[$item])!==false ):
            echo $base[$key]."<br>";
            $priorities[$base[$key]]['count']++;
            $priorities[$base[$key]]['files'][$key]='';
            $this->bfn[$path][$key]['dcount']=$priorities[$base[$key]]['count'];
        endif;
     endforeach;  
  endforeach;

  foreach ( $priorities as $base => $arr ):
//     print_r($arr);
     foreach ($arr['files'] as $filename => $empty ):     
     echo "*$filename";
     $this->priorities[$path][0][]=$arr['count'];
     $this->priorities[$path][1][]=$filename;
     endforeach;
  endforeach;

Je tam ještě malá chyba, že pokud poslední soubor nemá žádný podobný soubor k sobě, tak pole $arr je skoro prázdné a count je 0. To je tím, že pokud jméno aktuálního souboru==jméno souboru pak se přeskočí cyklus: if ($key==$f) continue;. Snad to nějak vyřeším.

Výsledné pole $this->priorities už má správnou podobu, takže ho už mohu použít na uspořádání.

Array
(
[test/Blansko/] => Array
(
[0] => Array
(
[0] => 1
[1] => 1
[2] => 1
[3] => 1
[4] => 1
[5] => 1
[6] => 1
[7] => 1
[8] => 1
[9] => 1
[10] => 1
[11] => 1
[12] => 1
[13] => 3
[14] => 3
[15] => 3
[16] => 1
[17] => 1
)

[1] => Array
(
[0] => Bedøichov.kml
[1] => Boøitov.kml
[2] => Brov-Jeneè.kml
[3] => Býkovice.kml
[4] => Drnovice.kml
[5] => Holštejn.kml
[6] => Lysice.kml
[7] => Obora.kml
[8] => Sloup.kml
[9] => Suchdol (Blansko).kml
[10] => Vavøinec.kml
[11] => Veselice.kml
[12] => újezd u Boskovic.kml
[13] => Èerná Hora 1.kml
[14] => Èerná Hora 2.kml
[15] => Èerná Hora 3.kml
[16] => Šošùvka.kml
[17] => Štìchov.kml
)

)

)


U posledního souboru by se asi neměl provádět příkaz if ($key==$f) continue;, aby se mohl poslední soubor zapsat do pole. Ale jak mám zjistit, že jde o poslední soubor? Jak poznat, že se pracuje s klíčem posledního prvku pole?

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:

0