回答編集履歴

1

a

2020/01/22 14:43

投稿

papinianus
papinianus

スコア12705

test CHANGED
@@ -1,19 +1,107 @@
1
- 上からマッチさせたい順なら発見次第ブレークすればよさそう。
2
-
3
- というか現状のコードを実行すると、リンクが多重につきそうだが。
4
-
5
1
  ```javascript
6
2
 
7
- if(check !== null)
3
+ function q236809() {
8
4
 
9
- {
5
+ const str = '東京都知事が東京都の財政について、道知事や府知事、特に大阪府知事と東京のある場所で語った。';
10
6
 
11
- var Url = val[i][1];
7
+ const arr = [["東京都知事","tky_chiji"],["東京都","tky_metro"],["東京", "tky"],["大阪府知事","osk_chiji"],["大阪府","osk_metro"],["府知事", "fuchiji"], ["、", "punct"]];
12
8
 
13
- newText = newText.replace(word, ' <a href="'+Url+'" target="blank">' +word+ '</a> ');
9
+ Logger.log(ProcessText(arr, str));
14
10
 
15
- break;//これ
11
+ }
16
12
 
13
+ function ProcessText(val, text)
14
+
15
+ {
16
+
17
+ const dic = val.reduce(function (a,c) {
18
+
19
+ a[c[0]] = c[1];
20
+
21
+ return a;
22
+
23
+ },{});
24
+
25
+ var poses = toPos(text);
26
+
27
+ Object.keys(dic).forEach(function (e) { getPoses(text,e).forEach(function (f) { if(poses[f] < f + e.length) { poses[f] = f + e.length;}})});
28
+
29
+ var cursor = 0;
30
+
31
+ var ret = "";
32
+
33
+ for(var s = 0; s < poses.length;) {
34
+
35
+ var e = poses[s];
36
+
37
+ if (s === e) { s++; continue;}
38
+
39
+ var needle = text.substring(s,e);
40
+
41
+ ret += text.substring(cursor,s) + anchor(needle, dic[needle]);
42
+
43
+ cursor = e;
44
+
45
+ s = e;
46
+
17
- }
47
+ }
48
+
49
+ ret += text.substring(cursor);
50
+
51
+ return ret;
52
+
53
+ }
54
+
55
+ function anchor(word, url) {
56
+
57
+ return ' <a href="'+url+'" target="blank">' +word+ '</a> ';
58
+
59
+ }
60
+
61
+ function toPos(str) {
62
+
63
+ return str.split("").map(function(_,i){ return i;});
64
+
65
+ }
66
+
67
+ function getPoses(haystack, needle) {
68
+
69
+ var ret = [];
70
+
71
+ var pos = haystack.indexOf(needle);
72
+
73
+ const len = needle.length;
74
+
75
+ while (pos !== -1) {
76
+
77
+ ret.push(pos);
78
+
79
+ pos = haystack.indexOf(needle, pos + len);
80
+
81
+ }
82
+
83
+ return ret;
84
+
85
+ }
18
86
 
19
87
  ```
88
+
89
+
90
+
91
+ ProcessText を作り直しました。ついでに補助関数を定義。
92
+
93
+ q2368089() で検証。
94
+
95
+ arrが、シートに書いてあるキーワードのサンプル。str は置換対象の文章。
96
+
97
+ 想像している要件は、同じワードがくりかえし出現しても対応する、マッチする範囲が重複したとき、先に開始し他のワードに包含されないものを採用する、ということ。
98
+
99
+ 例えば、東京都立と都立大学がキーワードとしてあったとき、このコードだと、東京都立が優先する。この辺どうなんでしょう。要件が不明でした。なお、このコードだと後者が都立航空高専であっても、東京都立を優先してしまう。だからロンゲストマッチですらない。
100
+
101
+
102
+
103
+ 今回は、データを加工できるとわからない(それは回答者には決められないから)状態で加工せずに解決できそうな方法として提示しました。
104
+
105
+
106
+
107
+ で、こういう面倒なコードをかくより、そのシートで東京都知事と東京都と東京は同じurlであるか、もしくは、東京都知事と東京都と東京が同じグループなんだということをC列にグルーピング順位として持たせて、同じグループなら、より文字の長いものを優先することにすれば、質問者様の ProcessText のループをいじるだけでできそう(できるとは言ってない)。データにグルーピングおよびグルーピングが順位として表現されていれば東京都立と都立航空高専の優先度を人間の意図どおり表現できる。