2017-08-09 1 views
1

Ich habe eine Tabelle mit Buchtiteln - die meisten von ihnen werden mehrmals für verschiedene Editionen veröffentlicht. Viele Titel wurden fälschlicherweise mit fehlenden Nicht-ASCII-Zeichen importiert, d. H. "La métamorphose" wurde in "La m? Tamorphose" umgewandelt, manchmal wurde é in ein Leerzeichen umgewandelt oder einfach von der Zeichenkette entfernt.Wie finde ich Zeichenketten, bei denen man Nicht-ASCII-Zeichen entfernt habe

Die Tabelle

editionid | bookid | title 
-------------------------------------------- 
1   | 1  | Elementarne čestice 
2   | 1  | Elementarne ?estice 
3   | 1  | Elementarne estice 
4   | 1  | Las partículas elementales 
5   | 2  | Schöne neue Welt 
6   | 2  | Sch ne neue Welt 

ich den Nicht-ASCIIs des Titels durch Strippen und im Vergleich zu anderen Titeln des gleichen Buchs der falschen Titel identifizieren will. Wenn es eine Übereinstimmung gibt, fand ich einen fehlerhaften Titel.

Ergebnis:

o.title (flawed) | e.title (good) 
----------------------------------- 
Elementarne ?estice | Elementarne čestice 
Elementarne estice | Elementarne čestice 
Sch ne neue Welt | Schöne neue Welt 

Der Tisch ist ziemlich groß, aber da muss ich nur einmal Leistung zu tun ist, nicht drücken.

Mein Ansatz:

select distinct on (o.editionid) o.title, e.title 
from editions o 
inner join editions e on (o.bookid = e.bookid) 
where o.bookid between 1 and 1000 
    and e.title !~ '^[ -~]*$' -- only for performance 
    and ((
     e.title like '%Þ%' and (o.title = regexp_replace(e.title, '[Þ]', '?') or o.title = regexp_replace(e.title, '[Þ]', ' ') or o.title = regexp_replace(e.title, '[Þ]', '')) 
    ) or (
     e.title like '%ß%' and (o.title = regexp_replace(e.title, '[ß]', '?') or o.title = regexp_replace(e.title, '[ß]', ' ') or o.title = regexp_replace(e.title, '[ß]', '')) 
    ) or (
     e.title like '%à%' and (o.title = regexp_replace(e.title, '[à]', '?') or o.title = regexp_replace(e.title, '[à]', ' ') or o.title = regexp_replace(e.title, '[à]', '')) 
    . 
    . 
    . 
    )) 

, die bisher funktioniert, aber es scheint unmöglich, alle Nicht-ASCII-Zeichen separat hinzuzufügen. Hat jemand eine Vorstellung von einem allgemeineren Ansatz, der alle Nicht-ASCII-Zeichen gleichzeitig abdeckt?

Zweitens - es funktioniert nicht, wenn zwei verschiedene Zeichen entfernt und ich weiß nicht, wie das zu lösen ist.

Und drittens vielleicht unmöglich - oft wurden nur einige Nicht-ASCIIs gedreht, aber nicht alle, also "Weiße Nächte" wurden zu "Wei e Nächte" - es wäre toll, wenn diese auch abgedeckt werden könnten.

+1

https://www.postgresql.org/docs/current/static/fuzzystrmatch.html Sie wollen wahrscheinlich das Konzept der "Entfernung bearbeiten" wie oben beschrieben. –

+0

Das wäre ziemlich fehleranfällig, da es nicht zwischen ASCII und nicht unterscheiden kann. – fisch

+0

d. H. "Exmple" vs. "exmple" haben die gleiche Distanz wie "example" vs. "exemple", wobei die letzten beiden in verschiedenen Sprachen absolut legitim sein könnten. – fisch

Antwort

0

Nach einigem es Hantieren war nicht so schwer, am Ende:

select distinct on (o.editionid) o.title as flawed, e.title as good 
from editions o 
inner join editions e on (o.bookid = e.bookid) 
where o.bookid between 0 and 10000 
    and e.title ~ '[^\x00-\x7F]' 
    and (
      o.title = regexp_replace(e.title, '[^\x00-\x7F]', '?', 'g') 
      or o.title = regexp_replace(e.title, '[^\x00-\x7F]', ' ', 'g') 
     ) 

regexp_replace(e.title, '[^\x00-\x7F]', '?', 'g') ist der Schlüssel, wo \x00-\x7F sind alle Unicode-Zeichen nicht im ASCII-Schema und 'g' halten in der gleichen Zeichenfolge für mehr Zugriffe auf der Suche .

Verwandte Themen