Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]7942[/thread]

regex matches zählen: mit keywords aus array



<< >> 6 Einträge, 1 Seite
steinwolf
 2006-05-04 20:36
#65568 #65568
User since
2003-08-04
367 Artikel
BenutzerIn
[default_avatar]
Ich habe folgende Aufgabenstellung:

In einem Array befinden sich an die 300 Worte, nach denen in einem String gesucht werden soll. Müsste also quasi mit jedem Keyword in einer schleife laufen glaube ich.

Als Ergebnis brauche ich die Anzahl der gefundenen Treffer, egal, ob die doppelt vorkommen oder nicht.

Die Hauptsache sind wiegesagt jeder einzelne Match.

Ich glaube nicht, dass ich das mit einem regex realisieren kann oder?
"Did you know? You can use your old motor oil to fertilize your lawn." - Blinkster - Professionelles EDV Forum
Strat
 2006-05-04 20:49
#65569 #65569
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
um die explizite schleife zu sparen, koennte man das folgendermaszen machen (vorausgesetzt, du hast keine RE-spezifischen sonderzeichen in @array:
Code: (dl )
1
2
3
4
5
6
my @array = qw(wort1 wort2 .... wortn);
my $re = join ("|", @array);
my %statistics = ();
foreach ( $string =~ m/($re)/g ) {
$statistics{$_}++;
}

falls du doch die schleife verwendest (koennte schneller sein), dann <!--perldoc_f1--><a href="http://faq.perl-community.de/bin/view/Perldoc/perl..." target="_blank"><img alt="perldoc " src="/iB_html/non-cgi/Skin/SKIN-3/images/perldoc.gif" border="0"> <!--perldoc_f2-->-f study<!--perldoc_f3--></a><!--perldoc_f4-->
auch die RE-option /o koennte interessant sein
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
steinwolf
 2006-05-04 21:01
#65570 #65570
User since
2003-08-04
367 Artikel
BenutzerIn
[default_avatar]
ääähmm...

ich merke, dass ich schon lange kein perl mehr programiert habe ^^

wie komme ich denn an den entgültigen zahlenwert?
"Did you know? You can use your old motor oil to fertilize your lawn." - Blinkster - Professionelles EDV Forum
Strat
 2006-05-04 21:12
#65571 #65571
User since
2003-08-04
5246 Artikel
ModeratorIn
[Homepage] [default_avatar]
ueber %statistics iterieren, z.B.
Code: (dl )
1
2
3
for my $word (sort keys %statistics) {
print "$word: $statistics{$word}\n";
} # for


nebenbei: wenn du nur komplette woerter und nicht auch teilwoerter finden willst, koennte
Code: (dl )
foreach ( $string =~ m/\b($re)\b/g ) {

helfen (sorry, habe ich uebersehen)
perl -le "s::*erlco'unaty.'.dk':e,y;*kn:ai;penmic;;print"
http://www.fabiani.net/
betterworld
 2006-05-04 21:24
#65572 #65572
User since
2003-08-21
2613 Artikel
ModeratorIn

user image
[quote=Strat,04.05.2006, 18:49]
Code: (dl )
1
2
3
foreach ( $string =~ m/($re)/g ) {
$statistics{$_}++;
}
[/quote]
Es waere vielleicht besser fuer beide Speicher und Prozessor, wenn man "while" statt "foreach" schreibt. Ansonsten ist es an dieser Stelle äquivalent, wenn ich mich nicht irre.\n\n

<!--EDIT|betterworld|1146763510-->
sid burn
 2006-05-05 00:24
#65573 #65573
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Da du ja sagtest das du nur die Anzahl brauchst, dann würde ich soetwas machen, ohne die Schleifen, und dem zwischen Hash, der dich ja anscheind nicht Interessiert.

Code (perl): (dl )
1
2
3
4
5
$string = "Hier sollte jetzt ein langer String sein, der auch hallo welt enthält. Wenn er nicht Hallo Welt enthält ist das auch nicht schlimm. weltstein sollte aber nicht gefunden werden.";

@woerter = qw/hallo welt/;
$woerter = join "|", @woerter;
$anz = () = $string =~ m/\b(?:$woerter)\b/g;

In $anz ist dann die gefunde Anzahl der Wörter enthalten. In diesem Fall wäre das "2". Wenn Groß- und Kleinschreibung egal ist, dann kannst du bei der Regex noch die Option /i hinzufügen, was dann die "richtige" Anzahl von 4 findet.


Allerdings ist eine Alternative mit 300 Elementen wohl alles andere als performant.



@strat
Quote
my $re = join ("|", @array);
...
...$string =~ m/($re)/g....

Das ist leider etwas falsch. Den er möchte ja die Wörter finden. Du machst zwar alles in einer Alternative. Allerdings überprüfst du nicht auf Wörter. Wenn wie bei mir nach "hallo" und "welt" gesucht wird, aber die begrenzer "\b" fehlen würde, dann würden 5 Treffer ausgegegeben werden, da "welt" auch auf "Weltstein" gematcht hat, was es ja eben nicht soll.

EDIT:
Ups, ganz überlesen dass du dich dich ja schon im Nachhinein verbessert hattest.


Die Option /o sollte man schon nehmen, da ein String in der Regex evauliert wird, und bei jedem durchlauf überprüft werden muss ob sich der String nicht verändert hat. Da der evaluierte String sich ja nicht ändert, gibt es keinen Grund gegen /o. Bei meiner version ist /o egal, da die Regex nicht in einer schleife vorkommt, und somit keine Überprüfungen stattfinden.

--------------------------------------

Ansonsten müssen für study besondere Anforderungen existieren, damit sich der mehraufwand von study erstmal lohnt.

1) Es darf in der Regex keine /i Option vorkommen. Wenn dies vorkommt hat Study keine Wirkung
2) Es darf keine Substitution benutzt werden, sobald der Suchstring einmal verändert wurde, hat study ebenfalls keine Wirkung.
3) Es müssen literale Elemente in der Regex vorkommen. Diese Literale dürfen aber ebenfalls nicht innerhalb von (?i) oder (?i:) vorkommen. Kommen keine Literalen Elemente vor. Bringt Study auch nichts.
4) Study verbraucht ca. 4 mal mehr Speicher als der String groß ist. Daher sollte man Study niemals auf sehr kleine Strings anwenden. Da die Listenerzeugung mit Study mehr Performance kostet als das Suchen
5) Bei großen Strings kann es enorme Vorteile bringen. Allerdings auch nur dann wenn man sehr viele unterschiedliche Regexe nacheinander auf den String anwendet, ohne den String zu verändern. Erst dann hat man einen Vorteil der Listenerzeugung von Study. Je mehr matches man auf den gleichen String macht, desto mehr lohnt sich study, bei weniger wird der Aufwand von study größer als der Performance Gewinn den es erzielen soll.
6) Study bringt nur absolut dann etwas bei einer Regex wenn ein bestimmter Literaler Text vorkommen [b]muss[\b]. Wenn alles nur alternativen, oder alles Optional ist, bringt es ebenfalls nicht. Zeichenklassen fallen ebenfalls weg. Weiterhin muss dieser Literaler Text herausgestellt werden. Also die Regex Engine muss erkennen können, dass dieser Text vorkommen muss. Das hat etwas mit dem schreiben der Regex zu tun.


Hier nochmal ein Zitat von Jeffrey E. F. Friedl wann study etwas bringt. Besser könnte ich es nicht beschreiben.

Quote
study ist dann von Nutzen, wenn ein großer Suchstring immer wieder abgesucht werden muss, ohne daß er dazwischen verändert wird. Ein gutes Beispiel ist das Filterprogramm, das ich beim Erstellen dieses Buches benutzt habe. Ich habe das Buch in einer selbstgezimmerten Sprache geschrieben, die durch diesen Filter in SGML übersetzt wird (das SGML wird danach in troff und schließlich PostScript umgesetzt). In diesem Filter wird jedes Kapitel zu einem einzigen String (dieses Kapitel ist etwa 475 Kilobyte groß). Auf diesen String wird eine große Anzahl von Tests angewandt, die ungültige Formatierungen erkennen sollen. Diese Tests verändern den Text nicht, sie prüfen nur; und sie suchen meist nach literalen Strings - das ist die Situation, die auf study zugeschnitten ist.

Aus dem buch Reguläre Ausdrücke. 2 Auflage Seite. 370.


Auser der größe des Strings (die ich ja nicht weiß) trifft aber kein einzige Sache zu die entscheident ist ob study Performance Vorteile erbringen könnte. Und selbst wenn die größe des Strings stimmen würde, würde study in diesem Fall nichts bringen.


EDIT: Regex und join optimiert.\n\n

<!--EDIT|sid burn|1146777327-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
<< >> 6 Einträge, 1 Seite



View all threads created 2006-05-04 20:36.