Better merge example

This commit is contained in:
Mike Farah 2021-11-29 21:28:25 +11:00
parent f5f148cadb
commit 176fec639d
2 changed files with 47 additions and 32 deletions

View File

@ -234,50 +234,60 @@ will output
``` ```
## Merge arrays of objects together, matching on a key ## Merge arrays of objects together, matching on a key
There are two parts of the complex expression. The first part is doing the hard work, it creates a map from the arrays keyed by '.a', There are several parts of the complex expression.
so that there are no duplicates. The second half converts that map back to an array. The first part is doing the hard work, it creates a map from the arrays keyed by '.a', so that there are no duplicates.
Then there's another reduce that converts that map back to an array.
Finally, we set the result of the merged array back into the first doc.
To use this, you will need to update '.[]' to be the expression to your array (e.g. .my.array[]), and '.a' to be the key field of your array (e.g. '.name') To use this, you will need to update '.myArray' to be the expression to your array (e.g. .my.array), and '.a' to be the key field of your array (e.g. '.name')
Thanks Kev from [stackoverflow](https://stackoverflow.com/a/70109529/1168223) Thanks Kev from [stackoverflow](https://stackoverflow.com/a/70109529/1168223)
Given a sample.yml file of: Given a sample.yml file of:
```yaml ```yaml
- a: apple myArray:
b: appleB - a: apple
- a: kiwi b: appleB
b: kiwiB - a: kiwi
- a: banana b: kiwiB
b: bananaB - a: banana
b: bananaB
something: else
``` ```
And another sample another.yml file of: And another sample another.yml file of:
```yaml ```yaml
- a: banana myArray:
c: bananaC - a: banana
- a: apple c: bananaC
b: appleB2 - a: apple
- a: dingo b: appleB2
c: dingoC - a: dingo
c: dingoC
``` ```
then then
```bash ```bash
yq eval-all ' yq eval-all '
((.[] | {.a: .}) as $item ireduce ({}; . * $item )) as $uniqueMap (
((.myArray[] | {.a: .}) as $item ireduce ({}; . * $item )) as $uniqueMap
| ( $uniqueMap | to_entries | .[]) as $item ireduce([]; . + $item.value) | ( $uniqueMap | to_entries | .[]) as $item ireduce([]; . + $item.value)
) as $mergedArray
| select(fi == 0) | .myArray = $mergedArray
' sample.yml another.yml ' sample.yml another.yml
``` ```
will output will output
```yaml ```yaml
- a: apple myArray:
b: appleB2 - a: apple
- a: kiwi b: appleB2
b: kiwiB - a: kiwi
- a: banana b: kiwiB
b: bananaB - a: banana
c: bananaC b: bananaB
- a: dingo c: bananaC
c: dingoC - a: dingo
c: dingoC
something: else
``` ```
## Merge to prefix an element ## Merge to prefix an element

View File

@ -29,17 +29,22 @@ var mergeArrayWithAnchors = `sample:
- <<: *a - <<: *a
` `
var mergeArraysObjectKeysText = `There are two parts of the complex expression. The first part is doing the hard work, it creates a map from the arrays keyed by '.a', var mergeArraysObjectKeysText = `There are several parts of the complex expression.
so that there are no duplicates. The second half converts that map back to an array. The first part is doing the hard work, it creates a map from the arrays keyed by '.a', so that there are no duplicates.
Then there's another reduce that converts that map back to an array.
Finally, we set the result of the merged array back into the first doc.
To use this, you will need to update '.[]' to be the expression to your array (e.g. .my.array[]), and '.a' to be the key field of your array (e.g. '.name') To use this, you will need to update '.myArray' to be the expression to your array (e.g. .my.array), and '.a' to be the key field of your array (e.g. '.name')
Thanks Kev from [stackoverflow](https://stackoverflow.com/a/70109529/1168223) Thanks Kev from [stackoverflow](https://stackoverflow.com/a/70109529/1168223)
` `
var mergeExpression = ` var mergeExpression = `
((.[] | {.a: .}) as $item ireduce ({}; . * $item )) as $uniqueMap (
((.myArray[] | {.a: .}) as $item ireduce ({}; . * $item )) as $uniqueMap
| ( $uniqueMap | to_entries | .[]) as $item ireduce([]; . + $item.value) | ( $uniqueMap | to_entries | .[]) as $item ireduce([]; . + $item.value)
) as $mergedArray
| select(fi == 0) | .myArray = $mergedArray
` `
var docWithHeader = `# here var docWithHeader = `# here
@ -378,11 +383,11 @@ var multiplyOperatorScenarios = []expressionScenario{
{ {
description: "Merge arrays of objects together, matching on a key", description: "Merge arrays of objects together, matching on a key",
subdescription: mergeArraysObjectKeysText, subdescription: mergeArraysObjectKeysText,
document: `[{a: apple, b: appleB}, {a: kiwi, b: kiwiB}, {a: banana, b: bananaB}]`, document: `{myArray: [{a: apple, b: appleB}, {a: kiwi, b: kiwiB}, {a: banana, b: bananaB}], something: else}`,
document2: `[{a: banana, c: bananaC}, {a: apple, b: appleB2}, {a: dingo, c: dingoC}]`, document2: `myArray: [{a: banana, c: bananaC}, {a: apple, b: appleB2}, {a: dingo, c: dingoC}]`,
expression: mergeExpression, expression: mergeExpression,
expected: []string{ expected: []string{
"D0, P[], (!!seq)::- {a: apple, b: appleB2}\n- {a: kiwi, b: kiwiB}\n- {a: banana, b: bananaB, c: bananaC}\n- {a: dingo, c: dingoC}\n", "D0, P[], (doc)::{myArray: [{a: apple, b: appleB2}, {a: kiwi, b: kiwiB}, {a: banana, b: bananaB, c: bananaC}, {a: dingo, c: dingoC}], something: else}\n",
}, },
}, },
{ {