fix(m02-df): 36-2 마지막 대조 99.8% — 표 찾기 글은 대소문자까지 같아야(옛 find)

- Rule lookup 같음 = 글끼리 LEN + FIND(대소문자 가림) · Compute _lookup = _exact(글은 그대로 비교) — 「t_2」 「T_2」 · 「e」 「E」 줄이 둘 다 맞던 것
- 시험 test_m02_df_model 36
- 전수(sub4 범위규칙 칸 · 검색어 찾기 · 재료 입력 받은 뒤): 시험입력 1,469/1,472(99.8%) · 기본 입력 1,466(99.6%) · 남은 = 자료 빈 단가 · 없는 품목에서 옛 셈은 식째 비움 · 흐름은 0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VBToTCGk5dqDKeXCEP3vhk
This commit is contained in:
2026-10-02 01:34:53 +09:00
co-authored by Claude Opus 5.5
parent 2b3ba84fe5
commit 1ee1668368
3 changed files with 32 additions and 2 deletions
@@ -326,6 +326,11 @@ def _same(a: Any, b: Any) -> bool:
return False
def _exact(a: Any, b: Any) -> bool:
"""표 찾기 같음 — 글끼리는 대소문자까지(옛 find · Rule lookup FIND) · 그 밖은 엑셀 「=」."""
return a == b if isinstance(a, str) and isinstance(b, str) else _same(a, b)
def _compare(a: Any, op: str, b: Any) -> bool:
if op in ("=", "≠"):
return _same(a, b) == (op == "=")
@@ -371,7 +376,7 @@ def _lookup(rule: dict, block: Any, conds: dict) -> tuple[Any, str | None]:
col, want = str(c.get("col")), _cond_of(conds, c.get("from") or {})
if col in head:
i = head.index(col)
tests.append(lambda row, i=i, want=want: row[i] is None or _same(row[i], want))
tests.append(lambda row, i=i, want=want: row[i] is None or _exact(row[i], want))
elif col + dv.RANGE_LOW in head and col + dv.RANGE_HIGH in head:
lo, hi, x = (
head.index(col + dv.RANGE_LOW),
+7 -1
View File
@@ -204,7 +204,13 @@ function lookup(
const same = at(c.col);
const low = at(`${c.col}·아래`);
const high = at(`${c.col}·위`);
if (same) tests.push((r) => `OR(ISBLANK(${same}${r}),${same}${r}=${ref})`);
// 글끼리는 대소문자까지 같아야 맞음(옛 find · 「t_2」 ≠ 「T_2」) — FIND 는 대소문자를 가림
if (same)
tests.push(
(r) =>
`OR(ISBLANK(${same}${r}),IF(AND(ISTEXT(${same}${r}),ISTEXT(${ref})),` +
`AND(LEN(${same}${r})=LEN(${ref}),ISNUMBER(FIND(${ref},${same}${r}))),${same}${r}=${ref}))`,
);
else if (low && high) {
ups.push(high);
tests.push(
+19
View File
@@ -949,3 +949,22 @@ def test_화면_값_물음_조건_찾기_인력기계유가_검색어_틀_다른
designs = {"기계": "0201-0020", "지역": "전국평균"}
assert ["*", "기계", None, {"key": "GC000270", "designs": designs}, False] in qs
assert server == {"노무비": 123} # 서버가 셈한 다른 로직 출력이 있으면 그것
def test_표_찾기_글은_대소문자까지_같아야() -> None:
from M02_MasterTemplete.DataFlow import M02_DF_Compute as cp
block = [["구분", "값"], ["T_2", 1], ["t_2", 3], ["e", 0.96], ["E", 0.45]]
rule = {
"kind": "lookup",
"conds": [{"col": "구분", "from": {"box": "v", "name": "g"}}],
"col": "값",
}
gs = ["t_2", "T_2", "E", "e", "x"]
got = _run(
RULE
+ f"const block = {json.dumps(block)};\nconst rule = {json.dumps(rule, ensure_ascii=False)};\n"
f"out({json.dumps(gs)}.map(g => {{ const r = R.applyRule(rule, block, {{ g }}); return [r.value, r.why]; }}));"
)
assert got == [[3, None], [1, None], [0.45, None], [0.96, None], [None, "표에 없는 조건"]]
assert [list(cp._lookup(rule, block, {"g": g})) for g in gs] == got