feat(implode): add implode command — inverse of explode (#917)#3733
Merged
Conversation
Groups rows by key column(s) and joins values of another column with a separator. Supports multi-column -k selectors, single-column -v, -r/--rename, --skip-empty to drop empty tokens, and --sorted for O(1)-memory streaming on pre-sorted input. Default buffered path emits groups in first-seen order. Closes #917. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Regenerated by 'qsv --update-mcp-skills'. No behavioral changes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Tighten USAGE: --sorted is not O(1); memory is bounded by the size of the largest group, not the whole input. - Extract a small key/value extraction helper; share between the sorted and buffered paths. - In the buffered path, switch to std's HashMap Entry API so --skip-empty no longer clones the key on every hit. Satisfies clippy::map_entry while avoiding the allocation. - Replace the manual join loop in write_group with <[Vec<u8>]>::join. - Tests: add coverage for the value==key error (with stderr assertion), unknown key column, empty input, --sorted + --skip-empty, and --sorted with a composite key. Upgrade the value-multi-column test to also verify the stderr message. Refresh docs/help/implode.md and MCP skill JSON for the updated USAGE. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The two composite-key tests used ',' as both the implode separator and the CSV delimiter, which forced the joined visitor field to be quoted in the raw output and obscured what was being asserted. Switch to '|' so the separator is distinct from the delimiter. Addresses review #1620. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 52 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new qsv implode command (inverse of qsv explode) that groups rows by key column(s) and joins a single value column using a user-provided separator, with optional streaming support for pre-sorted input.
Changes:
- Added
implodecommand implementation with buffered (first-seen order) and--sortedstreaming modes, plus--skip-emptyand--rename. - Wired the command into
qsvandqsvlite, and added comprehensive integration tests. - Updated generated help/docs, README/TOC entries, and MCP skill metadata (including new
qsv-implodeskill JSON).
Reviewed changes
Copilot reviewed 64 out of 64 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/tests.rs | Registers the new test_implode integration test module under appropriate feature flags. |
| tests/test_implode.rs | Adds integration tests covering basic behavior, composite keys, rename, empty handling, streaming mode, and error paths. |
| src/mcp_skills_gen.rs | Includes implode in the MCP skills generation list. |
| src/mainlite.rs | Adds implode to qsvlite’s command list, enum, and dispatch. |
| src/main.rs | Adds implode to qsv’s help text, enum, and dispatch. |
| src/cmd/mod.rs | Exposes the new cmd::implode module behind the same feature gates as other lite-capable commands. |
| src/cmd/implode.rs | Implements the implode command (group-by keys + join value column; buffered and --sorted streaming paths). |
| README.md | Adds implode to the command list/table. |
| docs/help/TableOfContents.md | Adds implode to generated help TOC. |
| docs/help/implode.md | Adds generated help page for implode. |
| .claude/skills/qsv/qsv-blake3.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-cat.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-count.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-datefmt.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-dedup.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-describegpt.json | Skill metadata version bump to 19.1.0 (plus wording tweak in option description). |
| .claude/skills/qsv/qsv-diff.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-enum.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-excel.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-exclude.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-explode.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-extdedup.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-extsort.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-fill.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-fixlengths.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-fmt.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-frequency.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-geocode.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-headers.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-implode.json | Adds new MCP skill metadata for the implode subcommand. |
| .claude/skills/qsv/qsv-index.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-input.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-join.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-joinp.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-json.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-jsonl.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-luau.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-moarstats.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-partition.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-pivotp.json | Skill metadata version bump to 19.1.0 (plus clarified option descriptions). |
| .claude/skills/qsv/qsv-pragmastat.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-pseudo.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-rename.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-replace.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-reverse.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-safenames.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-sample.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-schema.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-search.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-searchset.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-select.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-slice.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-sniff.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-sort.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-sortcheck.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-split.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-sqlp.json | Skill metadata version bump to 19.1.0 (plus clarified compression option description). |
| .claude/skills/qsv/qsv-stats.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-table.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-template.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-to.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-tojsonl.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-transpose.json | Skill metadata version bump to 19.1.0. |
| .claude/skills/qsv/qsv-validate.json | Skill metadata version bump to 19.1.0. |
- tests: replace the `assert_err` + `output_stderr` pair in the two error-path tests with a single `output_stderr` call and a stderr assertion. `output_stderr` already runs the command; pairing it with `assert_err` ran each failing command twice. - Correct the MCP skill memory hint: implode buffers all input unless --sorted is used, so it is 'proportional', not 'constant'. Added 😣 to the README row so the generator emits the right hint; regenerated docs/help/implode.md, TableOfContents.md, and qsv-implode.json. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
qsv implodeas the inverse ofqsv explode: groups rows by key column(s) and joins the values of a single column with a separator, producing one row per group.-kselector, single-column-v, optional-r/--rename,--skip-empty(default keeps empty tokens for lossless round-trip with explode), and--sortedstreaming path for pre-sorted input (memory bounded by the largest group).qsvandqsvlite; includes generated help markdown, README/TOC entries, and MCP skill JSON.Closes #917.
Test plan
cargo build --locked --bin qsv -F all_featurescargo build --locked --bin qsvlite -F litecargo t implode -F all_features— 14/14 passcargo t implode -F lite— 14/14 passcargo t explode -F all_features— no regressioncargo clippy --bin qsv -F all_features— cleanprintf 'name,color\nJohn,blue\nJohn,yellow\nJohn,light red\nMary,red\n' | qsv implode -k name -v color -r colors ";"produces the expected outputimplode ";" | explode ";"recovers the original 4 rowsNotes
Test coverage includes: basic single-key, composite key (buffered +
--sorted),--rename, empty-value handling (default include +--skip-empty),--sortedstreaming,--no-headers, empty input, round-trip withexplode, value-column-must-be-single-column error, value-column-can't-also-be-a-key-column error, unknown key column error. Error-path tests assert the specific stderr message.🤖 Generated with Claude Code