テキストをロジックごとにフィルタリングしたいときがありますね。日本語が怪しい気もしますが、あることにします。
私は、青空文庫で「
と 」
の数が不釣り合いな文章を発見するためにしました。
高校数学の集合論の思い出話をするよりサンプルコードを読んでもらう方が早いと思うので読んでください。
サンプルコード
/**
* 引数の配列に基づいてテキストをロジックごとにフィルタリングする関数。
* @param {string[]} texts - フィルタリングするテキストの配列。
* @param {string[]} names - フィルタリングに使用する名前の配列。
* @returns {Object} - フィルタリングされたテキストを含むオブジェクト。
* - `and`: すべての名前が含まれるセクション。
* - `xor`: いずれかの名前が含まれるが、すべての名前が含まれていないセクション。
* - `not`: いずれの名前も含まないセクション。
*/
function logicFilter(texts, names) {
// 名前の配列に含まれるいずれかの名前が含まれるセクションをフィルタリング
const includesAny = sec => names.some(name => sec.includes(name));
// 名前の配列に含まれるすべての名前が含まれるセクションをフィルタリング
const includesAll = sec => names.every(name => sec.includes(name));
return {
// 名前の配列に含まれるすべての名前が含まれるセクションをフィルタリング
and: texts.filter(sec => includesAll(sec)),
// 名前の配列に含まれるいずれかの名前が含まれるが、すべての名前が含まれていないセクションをフィルタリング
xor: texts.filter(sec => includesAny(sec) && !includesAll(sec)),
// 名前の配列に含まれるいずれの名前も含まないセクションをフィルタリング
not: texts.filter(sec => !(includesAny(sec) || includesAll(sec)),
};
}
// 使用例
const names = ["「", "」"];
const text = document.querySelector("body > div.main_text").textContent.split("\n");
const obj = logicFilter(text, names);
console.assert(text.length === obj.and.length + obj.xor.length + obj.not.length
, "南無三!");
console.log(JSON.stringify(obj, null ,4));
-
obj.xor
がカッコが片方しかない行の配列 -
obj.and
がカッコが完備している行の配列 -
obj.not
はそれ以外の行の配列
を意味しています。
今回のオブジェクトを見ることで、「金色夜叉」ではカッコの数は同じだが、長いセリフに改行を入れていることがわかります。
コピペ用抽象化
/**
* キーワードに基づいて配列をフィルタリングします。
* @param {string[]} array - フィルタリングする配列
* @param {string[]} keywords - フィルタリングに使用するキーワードの配列
* @returns {Object} - フィルタリングされた結果のオブジェクト
*/
function logicFilter(array, keywords) {
/**
* 配列の要素がすべて指定されたキーワードを含むかどうかを確認します。
* @param {string} item - チェックする要素
* @returns {boolean} - すべてのキーワードが含まれる場合はtrue、それ以外の場合はfalse
*/
const includesAll = item => keywords.every(keyword => item.includes(keyword));
/**
* 配列の要素がいずれかの指定されたキーワードを含むかどうかを確認します。
* @param {string} item - チェックする要素
* @returns {boolean} - いずれかのキーワードが含まれる場合はtrue、それ以外の場合はfalse
*/
const includesAny = item => keywords.some(keyword => item.includes(keyword));
return {
// すべてのキーワードを含む要素の配列を取得します
and: array.filter(item => includesAll(item)),
// いずれかのキーワードを含み、すべてのキーワードを含まない要素の配列を取得します
xor: array.filter(item => includesAny(item) && !includesAll(item)),
// いずれのキーワードも含まない要素の配列を取得します
not: array.filter(item => !(includesAny(item) || includesAll(item))),
};
}