Merge pull request #522 from johnkerl/sort-within-records-recursive

Add a sort-within-record -r option
This commit is contained in:
John Kerl 2021-05-17 01:56:05 +00:00 committed by GitHub
commit 1ece1ecacc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 72 additions and 4 deletions

View file

@ -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]

View file

@ -1 +1 @@
mlr --from regtest/input/sort-within-records.dkvp sort-within-records
mlr --from regtest/input/sort-within-records.dkvp sort-within-records

View file

@ -1 +1 @@
mlr --json --from regtest/input/needs-sorting.json sort-within-records
mlr --json --from regtest/input/needs-sorting.json sort-within-records

View file

@ -0,0 +1 @@
mlr --json --from regtest/input/needs-sorting.json sort-within-records -r

View file

@ -0,0 +1,13 @@
{
"a": 1,
"b": 2
}
{
"a": 1,
"b": 2
}
{
"a": 1,
"b": 2,
"c": 3
}

View file

@ -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
}

View file

@ -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