文字列内の共通語を見つけるこんにちは、
一般的な単語とその数を印刷する次の jsl コードがあります。ただし、正しくカウントされていないようです。
得られた出力は次のとおりです:
commonWords = ["c1" => 3, "cate" => 3];
それはそうであるべきだ
commonWords = ["c1" => 3、"cate" => 3、"shotp" => 3];
何か提案はありますか?
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];ありがとう
自動化とスクリプトRe: 文字列内の共通語を見つけるいいですね! いくつかの変更点については、以下で説明します。
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];
;
主な変更点は、PatRepeat を使用して入力を 1 トークン (単語) ずつ処理し、最後にセンチネル セパレーターを追加することです。元のコードでは、1 つの単語のみを一致させようと文字列を処理し、その単語が文字列の末尾にないことを発見すると、一致の開始を 1 文字進めて再度一致させようとします。最後のセパレーターがないため、最後の "shotp" が見つかりません。pattest での作業は、センチネルが追加されると同時に事前に小文字化することで簡素化されます。
誰かが words() 関数を使った解決策を提案するはずです。この方法ではセンチネルは必要ありません。
編集: どういうわけか、私は過去のこの歩哨を見逃していました。
Re: 文字列内の共通語を見つけるJMPテーブルも活用できる
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);
必要に応じて実行できる小さな最適化もいくつかあります
Re: 文字列内の共通語を見つける@Craige_Halesもう一つの質問です。単語の順序を維持することは可能ですか。
commonWords = ["c1" => 3、"cate" => 3、"shotp" => 3];
すべきだ
CATE_N_C1_ショット
commonWords = ["cate" => 3, "c1" => 3, "shotp" => 3];
Re: 文字列内の共通語を見つける@jthi単語の順序を保持することは可能ですか?
正しくは、 words = ["cate" => 3, "c1" => 3, "shotp" => 3]; です。
Re: 文字列内の共通語を見つける多分。
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;
*/
throw() は、潜在的な問題を 1 つ警告する可能性があります。
Re: 文字列内の共通語を見つけるできます。ただし、データの例が 1 つしかない場合、何をすべきかを判断するのは少し面倒です。たとえば、同じ単語が同じ要素に複数回出現することはできますか? また、要素内で順序は変更できますか?
Re: 文字列内の共通語を見つけるもちろん、連想配列が必要な場合、JMP が行う方法以外の方法で配列を順序付けることはできませんが、ランクを利用して配列から取得した値を順序付けることはできます。
「jmp テーブル」ソリューションを維持しようとしています (いくつかの仮定を立てました)
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);