mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-29 10:40:22 +00:00
Merge pull request #522 from johnkerl/sort-within-records-recursive
Add a sort-within-record -r option
This commit is contained in:
commit
1ece1ecacc
8 changed files with 72 additions and 4 deletions
|
|
@ -729,6 +729,7 @@ which is the same as:
|
|||
Usage: mlr sort-within-records [options]
|
||||
Outputs records sorted lexically ascending by keys.
|
||||
Options:
|
||||
-r Recursively sort subobjects/submaps, e.g. for JSON input.
|
||||
-h|--help Show this message.
|
||||
================================================================
|
||||
Usage: mlr stats1 [options]
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
mlr --from regtest/input/sort-within-records.dkvp sort-within-records
|
||||
mlr --from regtest/input/sort-within-records.dkvp sort-within-records
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
mlr --json --from regtest/input/needs-sorting.json sort-within-records
|
||||
mlr --json --from regtest/input/needs-sorting.json sort-within-records
|
||||
|
|
|
|||
1
go/regtest/cases/verb-sort-within-records/0003/cmd
Normal file
1
go/regtest/cases/verb-sort-within-records/0003/cmd
Normal file
|
|
@ -0,0 +1 @@
|
|||
mlr --json --from regtest/input/needs-sorting.json sort-within-records -r
|
||||
0
go/regtest/cases/verb-sort-within-records/0003/experr
Normal file
0
go/regtest/cases/verb-sort-within-records/0003/experr
Normal file
13
go/regtest/cases/verb-sort-within-records/0003/expout
Normal file
13
go/regtest/cases/verb-sort-within-records/0003/expout
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"a": 1,
|
||||
"b": 2
|
||||
}
|
||||
{
|
||||
"a": 1,
|
||||
"b": 2
|
||||
}
|
||||
{
|
||||
"a": 1,
|
||||
"b": 2,
|
||||
"c": 3
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ func transformerSortWithinRecordsUsage(
|
|||
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameSortWithinRecords)
|
||||
fmt.Fprintln(o, "Outputs records sorted lexically ascending by keys.")
|
||||
fmt.Fprintf(o, "Options:\n")
|
||||
fmt.Fprintf(o, "-r Recursively sort subobjects/submaps, e.g. for JSON input.\n")
|
||||
fmt.Fprintf(o, "-h|--help Show this message.\n")
|
||||
|
||||
if doExit {
|
||||
|
|
@ -47,6 +48,7 @@ func transformerSortWithinRecordsParseCLI(
|
|||
// Skip the verb name from the current spot in the mlr command line
|
||||
argi := *pargi
|
||||
argi++
|
||||
doRecurse := false
|
||||
|
||||
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
|
||||
opt := args[argi]
|
||||
|
|
@ -58,6 +60,9 @@ func transformerSortWithinRecordsParseCLI(
|
|||
if opt == "-h" || opt == "--help" {
|
||||
transformerSortWithinRecordsUsage(os.Stdout, true, 0)
|
||||
|
||||
} else if opt == "-r" {
|
||||
doRecurse = true
|
||||
|
||||
} else {
|
||||
transformerSortWithinRecordsUsage(os.Stderr, true, 1)
|
||||
}
|
||||
|
|
@ -66,7 +71,7 @@ func transformerSortWithinRecordsParseCLI(
|
|||
// TODO: allow sort by key or value?
|
||||
// TODO: allow sort ascendending/descending?
|
||||
|
||||
transformer, err := NewTransformerSortWithinRecords()
|
||||
transformer, err := NewTransformerSortWithinRecords(doRecurse)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
|
|
@ -78,11 +83,19 @@ func transformerSortWithinRecordsParseCLI(
|
|||
|
||||
// ----------------------------------------------------------------
|
||||
type TransformerSortWithinRecords struct {
|
||||
recordTransformerFunc transforming.RecordTransformerFunc
|
||||
}
|
||||
|
||||
func NewTransformerSortWithinRecords() (*TransformerSortWithinRecords, error) {
|
||||
func NewTransformerSortWithinRecords(
|
||||
doRecurse bool,
|
||||
) (*TransformerSortWithinRecords, error) {
|
||||
|
||||
this := &TransformerSortWithinRecords{}
|
||||
if doRecurse {
|
||||
this.recordTransformerFunc = this.transformRecursively
|
||||
} else {
|
||||
this.recordTransformerFunc = this.transformNonrecursively
|
||||
}
|
||||
|
||||
return this, nil
|
||||
}
|
||||
|
|
@ -91,6 +104,14 @@ func NewTransformerSortWithinRecords() (*TransformerSortWithinRecords, error) {
|
|||
func (this *TransformerSortWithinRecords) Transform(
|
||||
inrecAndContext *types.RecordAndContext,
|
||||
outputChannel chan<- *types.RecordAndContext,
|
||||
) {
|
||||
this.recordTransformerFunc(inrecAndContext, outputChannel)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
func (this *TransformerSortWithinRecords) transformNonrecursively(
|
||||
inrecAndContext *types.RecordAndContext,
|
||||
outputChannel chan<- *types.RecordAndContext,
|
||||
) {
|
||||
if !inrecAndContext.EndOfStream {
|
||||
inrec := inrecAndContext.Record
|
||||
|
|
@ -98,3 +119,15 @@ func (this *TransformerSortWithinRecords) Transform(
|
|||
}
|
||||
outputChannel <- inrecAndContext // including end-of-stream marker
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
func (this *TransformerSortWithinRecords) transformRecursively(
|
||||
inrecAndContext *types.RecordAndContext,
|
||||
outputChannel chan<- *types.RecordAndContext,
|
||||
) {
|
||||
if !inrecAndContext.EndOfStream {
|
||||
inrec := inrecAndContext.Record
|
||||
inrec.SortByKeyRecursively()
|
||||
}
|
||||
outputChannel <- inrecAndContext // including end-of-stream marker
|
||||
}
|
||||
|
|
|
|||
|
|
@ -688,6 +688,26 @@ func (this *Mlrmap) SortByKey() {
|
|||
*this = *that
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
func (this *Mlrmap) SortByKeyRecursively() {
|
||||
keys := this.GetKeys()
|
||||
|
||||
lib.SortStrings(keys)
|
||||
|
||||
that := NewMlrmapAsRecord()
|
||||
|
||||
for _, key := range keys {
|
||||
// Old record will be GC'ed: just move pointers
|
||||
value := this.Get(key)
|
||||
if value.IsMap() {
|
||||
value.mapval.SortByKeyRecursively()
|
||||
}
|
||||
that.PutReference(key, value)
|
||||
}
|
||||
|
||||
*this = *that
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// PRIVATE METHODS
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue