最初のフィールドに基づいて行を部分的に一致させ、一致するフィールドから2番目のフィールドをマージしたいと思います。
入力例
Hello:World
Hell0:World2
Helllo:World1
Hel:world4
最初の4文字に基づいて一致した場合、予想される出力は次のようになります。
Hello:World,World2,World1
Hell0:World2,World,World1
Helllo:World1,World,World2
しかし、特定の文字数ではなく、パーセンテージに基づいて一致することが可能かどうか疑問に思います。したがって、一致は90%
最初の文字ではなく文字列に基づいています4
。
答え1
TXR Lispのソリューション:
$ txr soln.tl < data # 70% hard-coded in program
Hello:World,World2,World1
Hell0:World2,World,World1
Helllo:World1,World,World2
Hel:world4
パスワード:
(defvarl %pct% 70)
(defstruct item ()
key ;; original key
eff-key ;; %pct% percentage of original key
value ;; original value
value-vec ;; list headed by original, plus others from other items.
(:postinit (me)
;; Initialize eff-key by taking percentage of key.
(let* ((len (len me.key))
(pct-len (trunc (+ (* len %pct%) 50) 100)))
(set me.eff-key (take pct-len me.key)))
;; Initialize value list with original value.
(set me.value-vec (vec me.value))))
(let* ((items (keep-matches (`@key:@value` (get-lines))
(new item key key value value)))
(hash [group-by .eff-key items]))
;; iterate over all groups of items that have same eff-key
(dohash (eff-key group-items hash)
;; In each group, iterate over all pairs of items (product).
(each-prod ((i group-items)
(j group-items))
;; For each pair that isn't an item with itself, augment
;; the list, by pushing the other item's value onto value-vec.
(unless (eq i j)
(vec-push i.value-vec j.value))))
;; Produce output
(each ((i items))
(put-line `@{i.key}:@{i.value-vec ","}`)))
アイテムHel
は削除されませんでした。その項目の基準が何であるかは不明です。
たとえば、サイズ1グループに属するアイテムを削除できます(他のアイテムは同じ有効なキーを共有しません)。
これらの項目のvalue-vec
長さは1なので、それらを削除する方法は、ベクトルに複数の項目がある項目を印刷することです。
;; Produce output
(each ((i items))
(if (>= (len i.value-vec) 2)
(put-line `@{i.key}:@{i.value-vec ","}`)))