Suchen nach häufigen Wörtern in einer ZeichenfolgeHallo,
Ich habe den folgenden JSL-Code, der die gebräuchlichen Wörter und die Anzahl ausgibt. Allerdings scheint die Zählung nicht korrekt zu sein.
Die Ausgabe, die ich erhalte, ist:
gemeinsame Wörter = ["c1" => 3, "cate" => 3];
Es sollte
gemeinsame Wörter = ["c1" => 3, "cate" => 3, "shotp" => 3];
Irgendwelche Vorschläge?
input = "CATE_N_C1_Shotp,CATE_P_C1_Shotp,CATE_P_C1_Shotp";// input string<BR />
// Define boundary characters as _ and ,
boundaryChars = "_,";
// Define the pattern for boundary and word
boundaryPat = Pat Any( boundaryChars ) | Pat Pos( 0 );
wordPat = Pat Break( boundaryChars ) | Pat Rem();
patMatchWord = boundaryPat + Pat Pos()>>position + wordPat>>word + boundaryPat;
// Associative array to count word frequency
wordsToCount = [=>];
// Match pattern in the input
rc = Pat Match( input, patMatchWord
+ Pat Test(
word = Lowercase( word ); // Convert word to lowercase for uniformity
If( Contains( wordsToCount, word ),
wordsToCount[word] = wordsToCount[word] + 1,
wordsToCount[word] = 1
);
)
+ Pat R Pos( 0 ) // The pattern must reach the end
);
// Identify common words (those that appear in all elements)
elements = Words( input, "," );
totalElements = N Items( elements );
commonWords = [=>];
For Each( {{word, count}}, wordsToCount,
If( count == totalElements,
commonWords[word] = count
);
);
// Display the common words and their counts
Show( commonWords );<BR /><BR />// commonWords = ["c1" => 2, "cate" => 2];Danke
Automatisierung und SkriptingBetreff: Häufige Wörter in einer Zeichenfolge findenSchön! Ein paar Änderungen, unten erläutert.
input = "CATE_N_C1_Shotp,CATE_P_C1_Shotp,CATE_P_C1_Shotp";// input string
// Define boundary characters as _ and ,
boundaryChars = "_,";
// Associative array to count word frequency
wordsToCount = [=> ];
// Match pattern in the input
rc = Pat Match(
Lowercase( input ) || boundaryChars, // pre-normalize and add sentinel at end
Pat Pos( 0 )
+ Pat Repeat(
Pat Break( boundaryChars ) >> word + Pat Span( boundaryChars )
+ Pat Test(
If( Contains( wordsToCount, word ),
wordsToCount[word] = wordsToCount[word] + 1,
wordsToCount[word] = 1
);
1; // explicitly, result of pattest is 'true'
)
)
+ Pat R Pos( 0 ) // The pattern must reach the end
);
// Identify common words (those that appear in all elements)
elements = Words( input, "," );
totalElements = N Items( elements );
commonWords = [=> ];
For Each( {{word, count}}, wordsToCount, If( count == totalElements, commonWords[word] = count ) );
// Display the common words and their counts
Show( commonWords );// commonWords = ["c1" => 3, "cate" => 3, "shotp" => 3];
;
Die wichtigste Änderung besteht darin, PatRepeat zu verwenden, um die Eingabe Token für Wort durchzugehen und am Ende einen Sentinel-Trennzeichen hinzuzufügen. Ihr ursprünglicher Code durchläuft die Zeichenfolge, indem er versucht, nur ein Wort zu finden, dann feststellt, dass das Wort nicht am Ende der Zeichenfolge steht, den Anfang der Übereinstimmung um ein Zeichen vorrückt und erneut versucht, eine Übereinstimmung zu finden. Das letzte „shotp“ wird verpasst, da kein letztes Trennzeichen vorhanden ist. Die Arbeit in Pattest wird vereinfacht, indem gleichzeitig mit dem Hinzufügen des Sentinel vorab Kleinschreibung vorgenommen wird.
Ich bin ziemlich sicher, dass jemand eine Lösung mit der Funktion „words()“ vorschlagen wird, für die kein Sentinel erforderlich ist.
edit: Irgendwie habe ich diesen Wächter aus der Vergangenheit verpasst.
Betreff: Häufige Wörter in einer Zeichenfolge findenSie können auch JMP-Tabellen verwenden
Names Default To Here(1);
input = "CATE_N_C1_Shotp,CATE_P_C1_Shotp,CATE_P_C1_Shotp";
input = lowercase(input);
elements = Words(input, ",");
dt = New Table("Data",
New Column("Word", Character, Nominal),
New Column("Elementnr", Numeric, Nominal),
private
);
For Each({element, idx}, elements,
l = Words(element, "_");
nr = Repeat(idx, N Items(l));
r = N Rows(dt);
dt << Add Rows(N Items(l));
dt[r+1::r+N Items(l), 1] = l;
dt[r+1::r+N Items(l), 2] = nr;
);
dt_summary = dt << Summary(
Group(:Word),
N,
Subgroup(:Elementnr),
Freq("None"),
Weight("None"),
Link to original data table(0),
private
);
sums = V Sum((dt_summary[0, 3::N Cols(dt_summary)] > 0)`);
valid_idx = Loc(sums >= N ITems(elements));
words = Associative Array(dt_summary[valid_idx, 1], dt_summary[valid_idx, 2]);
Close(dt, no save);
Close(dt_summary, no save);
show(words);
Es gibt auch einige kleine Optimierungen, die bei Bedarf durchgeführt werden könnten
Betreff: Häufige Wörter in einer Zeichenfolge finden@Craige_Hales Noch eine Frage: Ist es möglich, die Reihenfolge der Wörter beizubehalten?
gemeinsame Wörter = ["c1" => 3, "cate" => 3, "shotp" => 3];
Sollte sein
CATE_N_C1_Shotp
gemeinsame Wörter = ["cate" => 3, "c1" => 3, "shotp" => 3];
Betreff: Häufige Wörter in einer Zeichenfolge finden@jthi, ist es möglich, die Wortreihenfolge beizubehalten?
Sollte sein: Wörter = ["cate" => 3, "c1" => 3, "shotp" => 3];
Betreff: Häufige Wörter in einer Zeichenfolge findenVielleicht.
input = "CATE_N_C1_Shotp,CATE_P_C1_Shotp,CATE_P_C1_Shotp";// input string
// Define boundary characters as _ and ,
boundaryChars = "_,";
position = 0;
wordToPosition = [=> ];
// Associative array to count word frequency
wordsToCount = [=> ];
// Match pattern in the input
rc = Pat Match(
Lowercase( input ) || boundaryChars, // pre-normalize and add sentinel at end
Pat Pos( 0 )
+ Pat Repeat(
Pat Break( boundaryChars ) >> word + Pat Span( boundaryChars ) >> sep
+ Pat Test(
position += 1;
If( Contains( wordsToCount, word ),
wordsToCount[word] = wordsToCount[word] + 1,
wordsToCount[word] = 1
);
If( Contains( wordToPosition, word ) & wordToPosition[word] != position,
throw("word ordering not consistent")
);
wordToPosition[word] = position;
if(sep==",", position = 0);
1; // explicitly, result of pattest is 'true'
)
)
+ Pat R Pos( 0 ) // The pattern must reach the end
);
// Identify common words (those that appear in all elements)
elements = Words( input, "," );
totalElements = N Items( elements );
commonWords = [=> ];
For Each( {{word, count}}, wordsToCount, If( count == totalElements, commonWords[word] = count ) );
// Display the common words and their counts
Show( commonWords );// commonWords = ["c1" => 3, "cate" => 3, "shotp" => 3];
Show( wordToPosition );// wordToPosition = ["c1" => 3, "cate" => 1, "n" => 2, "p" => 2, "shotp" => 4];
keys = wordToPosition << getkeys;//{"c1", "cate", "n", "p", "shotp"}
vals = wordToPosition << getvalues;// {3, 1, 2, 2, 4}
sort = Rank( vals );// [2, 3, 4, 1, 5]
keys = keys[sort];// {"cate", "n", "p", "c1", "shotp"}
vals = vals[sort];// {1, 2, 2, 3, 4}
For Each( {k}, keys, If( Contains( commonWords, k ), Show( k, commonWords[k] ) ) );
/*
k = "cate";
commonWords[k] = 3;
k = "c1";
commonWords[k] = 3;
k = "shotp";
commonWords[k] = 3;
*/
Die Funktion throw() macht Sie möglicherweise auf ein potenzielles Problem aufmerksam.
Betreff: Häufige Wörter in einer Zeichenfolge findenDas kann es. Mit nur einem Datenbeispiel ist es allerdings etwas mühsam herauszufinden, was zu tun ist. Kann beispielsweise dasselbe Wort mehrmals im selben Element vorkommen? Und kann sich die Reihenfolge innerhalb der Elemente ändern?
Betreff: Häufige Wörter in einer Zeichenfolge findenWenn Sie ein assoziatives Array benötigen, können Sie es natürlich nicht anders sortieren als in JMP, ABER Sie können die daraus erhaltenen Werte mithilfe von Rängen sortieren.
Ich versuche, bei der „JMP-Tabelle“-Lösung zu bleiben (ich habe einige Annahmen gemacht)
Names Default To Here(1);
input = "CATE_N_C1_Shotp,CATE_P_C1_Shotp,CATE_P_C1_Shotp";
input = lowercase(input);
elements = Words(input, ",");
dt = New Table("Data",
New Column("Word", Character, Nominal),
New Column("Elementnr", Numeric, Nominal)
);
For Each({element, idx}, elements,
l = Words(element, "_");
nr = Repeat(idx, N Items(l));
r = N Rows(dt);
dt << Add Rows(N Items(l));
dt[r+1::r+N Items(l), 1] = l;
dt[r+1::r+N Items(l), 2] = nr;
);
new_col1 = dt << New Column("C", Numeric, Continuous, Formula(
Col Number(:Elementnr, :Word)
));
new_col2 = dt << New Column("R", Numeric, Continuous, Formula(
Col Min(Col Cumulative Sum(1, :Elementnr), :Word)
));
dt << run formulas;
new_col1 << delete formula;
new_col2 << delete formula;
Summarize(dt, elem = by(:Elementnr));
element_count = N Items(elem);
dt << Delete Rows(dt << get rows where(:C != element_count));
dt << Select Duplicate Rows(Match(:Word)) << Delete Rows << Clear Select;
aa = Associative Array(:Word, :C); // results in AA
r = Rank(:Word << get values); // use Rank to return in original order
Close(dt, No save);
keys = (aa << get keys)[r];
// Values does not need sorting as they always have same values
values = aa << get values;
Write();
show(aa, r, keys, values);