jointable -n vergleicht Schlüssel als Zahlen, Review Punkt 9 abgeschlossen

This commit is contained in:
wkh
2026-10-30 10:07:48 +01:00
parent 158ce5dee2
commit d6733e737e
5 changed files with 30 additions and 11 deletions
+1
View File
@@ -42,6 +42,7 @@ folgen [Semantic Versioning](https://semver.org/lang/de/). Die Version steht in
- Tabellen, Indexdateien und `substitute` werden über eine temporäre Datei mit `rename` geschrieben; ein Abbruch lässt die alte Datei statt einer halben neuen.
- `index -mb` und `-mi` sortieren nach dem Schlüssel ohne umgebende Leerzeichen, so wie `search` vergleicht.
- `sorttable -r` kehrte auch die Reihenfolge gleicher Schlüssel um; sie bleibt jetzt erhalten.
- `jointable -n` wurde stillschweigend ignoriert. Wie in der Man-Page vergleicht es die Schlüssel jetzt als Zahlen (`01`, `1` und ` 1.0` passen zusammen).
- Spaltennamen, die `justify` mit Leerzeichen aufgefüllt hat, wurden nicht mehr gefunden: `column Name` lieferte eine leere Spalte, `index` brach ab. Leerraum um die Namen im Kopf zählt jetzt nicht mehr.
## [0.7.0] - 2026-10-12
+1 -1
View File
@@ -13,7 +13,7 @@ sind nach dem Handbuch neu geschrieben.
mise trust # einmal nach dem Clone: mise.toml freigeben
mise install # Ruby 3.4
mise run install # legt die Symlinks row, column, total ... in bin/ an
mise run test # 131 Tests und die Beispiele aus dem Handbuch
mise run test # 132 Tests und die Beispiele aus dem Handbuch
```
Ohne `mise trust` brechen in einem frisch geklonten Ordner alle `mise`-Befehle ab.
+10 -4
View File
@@ -67,10 +67,16 @@ gelesen), 3 (Fehler als eine Zeile, `RDB_DEBUG=1` für den Backtrace), 4 (`EDITO
Argumenten, Editorfehler wird gemeldet), 5 (Satz wird in jedem Fall zurückgeschrieben),
6 (`Rdb.check_cells!`), 7 (`Rdb.write_file`: temporäre Datei plus `rename`) und 8
(Sortierschlüssel ohne Leerzeichen) sind behoben, jeweils mit Test.
Bei 9 ist nur `sorttable -r` behoben. Bewusst offen: `-nrf` gilt global (so beschreibt es
das Handbuch), `jointable -n` ist unklar spezifiziert, `1e3` als Zahl und die Zeile aus
leeren Zellen als „gelöscht“ sind Eigenheiten des Formats. Bei 8 bleibt `-x` (Faltung) beim
Index ohne Entsprechung in der Suche offen.
Bei 9 sind `sorttable -r` (stabil) und `jointable -n` (Schlüssel als Zahlen, wie in der
Man-Page) behoben. Bleibt so (Entscheidung 2026-10-30):
- `-nrf` gilt für alle Spalten: laut Man-Page reicht `sorttable` die Optionen an `sort`
weiter, Optionen pro Spalte gibt es im Original nicht.
- `1e3` ist keine Zahl: sonst würden Spalten mit Codes wie `2E5` numerisch.
- Eine Zeile aus lauter leeren Zellen gilt als gelöscht: so arbeitet `delete` im Format.
Offen bei 8: `index -x` (gefaltet) hat in `search` ohne `-x` kein Gegenstück, weil die
`.i`-Datei die Faltung nicht vermerkt. Das bräuchte eine Markierung im Indexkopf.
## Verbesserungspotential
+8 -6
View File
@@ -96,7 +96,7 @@ end
Rdb.register('jointable', 'Join two tables into one where keys match',
'jointable [-a[1|2]] [-j[1|2] column]... [-n] [-] table1 [table2]') do |args|
all1 = all2 = false
all1 = all2 = numeric = false
k1 = k2 = nil
files = []
until args.empty?
@@ -108,7 +108,7 @@ Rdb.register('jointable', 'Join two tables into one where keys match',
when '-j' then k1 = k2 = args.shift
when '-j1' then k1 = args.shift
when '-j2' then k2 = args.shift
when '-n' then nil
when '-n' then numeric = true
else files << a
end
end
@@ -119,13 +119,15 @@ Rdb.register('jointable', 'Join two tables into one where keys match',
i1 = k1 ? t1.index_of(k1) : 0
i2 = k2 ? t2.index_of(k2) : 0
keep2 = (0...t2.head.size).to_a - [i2]
# -n compares keys as numbers: 01, 1 and " 1.0" are the same key
key = ->(v) { numeric && numeric?(v) ? Rdb.decimal(v) : v }
by_key = Hash.new { |h, k| h[k] = [] }
t2.rows.each { |r| by_key[r[i2]] << r }
t2.rows.each { |r| by_key[key.(r[i2])] << r }
used = {}
out = []
t1.rows.each do |r|
if (m = by_key[r[i1]]).any?
used[r[i1]] = true
if (m = by_key.fetch(key.(r[i1]), [])).any?
used[key.(r[i1])] = true
m.each { |r2| out << r + keep2.map { |i| r2[i] } }
elsif all1
out << r + [''] * keep2.size
@@ -133,7 +135,7 @@ Rdb.register('jointable', 'Join two tables into one where keys match',
end
if all2
t2.rows.each do |r2|
next if used[r2[i2]]
next if used[key.(r2[i2])]
blank = [''] * t1.head.size
blank[i1] = r2[i2]
+10
View File
@@ -961,3 +961,13 @@ class ExactnessTest < RdbCase
assert_equal 'v500', data_obj.row_at(data_obj.rows.last.from).cells[1]
end
end
class JoinNumericTest < RdbCase
def test_jointable_n_matches_keys_as_numbers
write('j1', "K\tA\n-\t-\n01\tx\n 2\ty\n3\tz\n")
write('j2', "K\tB\n-\t-\n1\tp\n2.0\tq\n")
assert_empty data(rdb('jointable', 'j1', 'j2'))
assert_equal [%w[01 x p], [' 2', 'y', 'q']], data(rdb('jointable', '-n', 'j1', 'j2'))
assert_equal 3, data(rdb('jointable', '-n', '-a1', 'j1', 'j2')).size
end
end