21. září bude sraz! Od 18.00 v restauraci Tradice v Praze u Anděla
Autor Zpráva
sysel
Profil
aneb hledání společné části dvou řetězců

V jedné položce záznamu mám uloženu cestu k souboru a potřebuji nalézt záznamy s předpokládatelnou duplicitou, tj. vybrat cesty, které se nejvíce podobají.
Je to tedy problém, kdy potřebuji porovnat dva řetězce a ohodnotit, jak dlouhou mají společnou část - myšleno odzadu, od názvu souboru. Porovnání je vlastně kvantováno po celých adresářích, protože částečná shoda názvu dvou adresářů není zajímavá. Cesta je v UNIXovém formátu - tedy s "/" jako separátorem názvů podadresářů, ale nemám problém pochopit "\" nebo ":"

Lze na to použít nějakou standardní funkci v Postgresu?

Děkuji předem za rady

sysel
Kajman
Profil
Asi si musíte přidat vlastní funkci, např.
okbob.blogspot.cz/2010/06/longest-common-substring-of-two-strings.html
sysel
Profil
Jo jo! to vypadá přesně jako to, co se mi nepodařilo vygooglovat!
Díky moc.
juriad
Profil
V tomto případě by šlo funkci substrings z toho odkazu zjednodušit, aby vracela jen všechny podřetězce od každého místa až do konce, připadě jen od lomítek do konce řetězce. Asi tě příliš nezajímá shoda na začátku cesty.
sysel
Profil
juriad:
Ano, nezajímá, také jsem na to myslel. Blbé je na tom to obrácené pořadí. Na rozparsování cesty lze použít regexp_split_to_array, ale pak to znamená doučit se honem array_functions
tiso
Profil
sysel: mne sa nezdá to tvoje zadanie. Čo to vlastne chceš dosiahnuť? Pomohol by aj príklad.
sysel
Profil
S pomocí rad, manuálů a nápovědy jsem dal dohromady tohle:

CREATE OR REPLACE FUNCTION compath(cesta1 text, cesta2 text)
  RETURNS text AS $BODY$
DECLARE 
    pc1 text[]; d1 integer; delta1 integer :=0;
    pc2 text[]; d2 integer; delta2 integer :=0;
    dmin integer; maxi integer;
BEGIN
    pc1:=string_to_array(cesta1, '/' ); d1:=array_length(pc1, 1);
    pc2:=string_to_array(cesta2, '/' ); d2:=array_length(pc2, 1);
    IF d1>d2 THEN dmin:=d2; delta1:=d1-d2;
             ELSE dmin:=d1; delta2:=d2-d1;
    END IF;
    FOR i IN REVERSE dmin .. 1 LOOP 
      IF pc1[i+delta1] LIKE pc2[i+delta2] THEN maxi:=i; 
       ELSE RETURN array_to_string(pc1[(maxi+delta1):d1],'/');
      END IF;
    END LOOP;
    RETURN array_to_string(pc1[(maxi+delta1):d1],'/');
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE

a chodí to, i jdyž asi ne nejrychleji.

Pro tiso: tak jak to dělá řada lidí - vytvoří si adresář na ploše, stáhnou si do něj fotky, ty upraví a upravené nastrkají do podadresáře, pak si v upravených vyberou, co dají na web .....
No a pak si celý adresář z plochy překopírují někam na flešku nebo NAS do nějakých archivních či backupových adresářů. Tak se soubory pomnoží a aby se v tom ..(ošklivé slovo jsem vymazal sám).. vyznalo.
Cíl je tedy jasný - pokusit se nějak ztotožnit jinak stejně vypadající IMG0012.JPG. Jasně vím, že je na to řada programů a fíglů pomocí MD5 aj. atd. Ale když je souborů několik milionů a jde o několik počítačů najednou, tak je to zajímavá úloha na procvičení :-)
tiso
Profil
sysel: „Cíl je tedy jasný - pokusit se nějak ztotožnit jinak stejně vypadající IMG0012.JPG.
Nemyslím si že toto tvoje riešenie je dobrý nápad, môže slúžiť len na prvú identifikáciu "rovnakých" súborov, ale potom musíš siahnuť po tých osvedčených (Checksum, ...).
sysel
Profil
tiso:
No trochu mi chybí ty vlastní soubory, mám jen staženou adresářovou strukturu pomocí find . -type f -iname "*.jpg" >obrazky.txt, ale když nic jiného, je to zajímavé procvičení

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