![부분적으로 행 일치 및 병합](https://linux55.com/image/210049/%EB%B6%80%EB%B6%84%EC%A0%81%EC%9C%BC%EB%A1%9C%20%ED%96%89%20%EC%9D%BC%EC%B9%98%20%EB%B0%8F%20%EB%B3%91%ED%95%A9.png)
첫 번째 필드를 기반으로 행을 부분적으로 일치시키고 일치하는 필드에서 두 번째 필드를 병합하고 싶습니다.
입력 예
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 ","}`)))