How to combine a list of objects to a map of list with a custom key based on a field value in Groovy? - groovy

Hi I'm new to Groovy and have been trying this out but could not come up with a correct solution.
Basically I have a list of objects that i would need to correlate part of a specific field and put it in a map with a transformed key. Given example below, I need correlate the values of the third field by the first four characters (e.g. key3,key4) and put them in a map. So all key3 objects and key4 objects in a separate map and combine them in 1 map with key3 and key4 as the keys and their original values in a list.
Foo[] foo = [
["field1a", "field2a", "key3a"],
["field1b", "field2b", "key3b"],
["field1c", "field2c", "key4c"]
]
into
result = [
"key3":[
["field1a", "field2a", "key3a"],
["field1b", "field2b", "key3b"]
],
"key4":[
["field1c", "field2c", "key4c"]
]
]
So far i've been able to get the unique keys by using a combination of collect(), substring() and unique(), but i am unable to build the map properly. I've used collectEntries() but it only creates a map of the object and not a map of lists.
If anyone can point me in the right direction it would really be a big help. Thanks!

Using groupBy.
assert foo.groupBy { it[-1][0..-2] } == [
key3:[
['field1a', 'field2a', 'key3a'],
['field1b', 'field2b', 'key3b']
],
key4:[
['field1c', 'field2c', 'key4c']
]
]
Explanation:
Group by the third/last element in the list it[-1] but only consider the substring key3, hence it[-1][0..-2]

Related

How do i get only the Json keys as a output from ADF lookup activity

This is my json which read via a lookup activity
{
"key1" : { "id" = "100" },
"key2" : "XYZ",
"key3" : [1,2,3]
}
I need a activity that gives me all the keys alone from above json
Lookup.output.firstrow.key2 gives me the string XYZ
What expression i can use to get all the keys alone
I really looking for some expression like Lookup.output.firstrow.getKeys() which returns array of keys such as
["key1", "key2", "key3"]
How do i get only the Json keys as a output from ADF lookup activity
There is no such direct way to achieve this you have to do it by setting the variables and string manipulation.
Follow below procedure:
I took json file in look up and its output is as follow:
To get all keys from above Json first I took set variable activity and created a demo string variable with value.
#substring(string(activity('Lookup1').output.value),2,sub(length(string(activity('Lookup1').output.value)),4))
here we are converting lookup output to string and removing braces from start and end.
Then I took another set variable activity and created a demo2 array variable with value.
#split(substring(string(split(variables('demo'),':')),2,sub(length(string(split(variables('demo'),':'))),4)),',')
Here we are splitting the string with : and ,
Then I created an array with default range of even numbers of values 0,2,4,6 etc.
Then Passed it to ForEach activity
Then Inside For Each activity I took append variable activity and gave value as
#variables('demo2')[item()]
Output:
Note: if your values contain : or , the above expression will also split those values. and if we split the values with : then I will split the string with : only and rest thing it will consider as single value. In below image the highlighted value it is taking as single value.

Remove a map item in terraform

If I use the following yamldecode, I get the following output:
output "product" {
value = distinct(yamldecode(file("resource/lab/abc.yaml"))["account_list"]["resource_tags"][*]["TAG:product"])
}
Output:
+ product = [
+ "fargate",
+ "CRM",
]
I want fargate to be removed from my output and the expected output is this:
+ product = [
+ "CRM"
]
Please let me know how I can do this.
output "product" {
value = compact([for x in distinct(yamldecode(file("resource/lab/abc.yaml"))["account_list"]["resource_tags"][*]["TAG:product"]) : x == "fargate" ? "" : x])
}
I get this output:
test = [
"enter",
]
compact function solved the problem.
The Terraform language is based on functional principles rather than imperative principles and so it does not support directly modifying an existing data structure. Instead, the best way to think about goals like this is how to define a new value which differs from your existing value in some particular way.
For collection and structural types, the most common way to derive a new value with different elements is to use a for expression, which describes a rule for creating a new collection based on the elements of an existing collection. For each element in the source collection we can decide whether to use it in the result at all, and then if we do decide to use it we can also describe how to calculate a new element value based on the input element value.
In your case you seem to want to create a new list with fewer elements than an existing list. (Your question title mentions maps, but the question text shows a tuple which is behaving as a list.)
To produce a new collection with fewer elements we use the optional if clause of a for expression. For example:
[for x in var.example : x if x != "fargate"]
In the above expression, x refers to each element of var.example in turn. Terraform first evaluates the if clause, and expects it to return true if the element should be used. If so, it will then evaluate the expression immediately after the colon, which in this case is just x and so the result element is identical to the input element.
Your example expression also includes some unrelated work to decode a YAML string and then traverse to the list inside it. That expression replaces var.example in the above expression, as follows:
output "products" {
value = toset([
for x in yamldecode(file("${path.module}/resource/lab/abc.yaml"))["account_list"]["resource_tags"][*]["TAG:product"]: x
if x != "fargate"
])
}
I made some other small changes to the above compared to your example:
I named the output value "products" instead of "product", because it's returning a collection and it's Terraform language idiom to use plural names for collection values.
I wrapped the expression in toset instead of distinct, because from your description it seems like this is an unordered collection of unique strings rather than an ordered sequence of strings.
I added path.module to the front of the file path so that this will look for the file in the current module directory. If your output value is currently in a root module then this doesn't really matter because the module directory will always be the current working directory, but it's good practice to include this so that it's clear that the file belongs to the module.
Therefore returning a set is more appropriate than returning a list because it communicates to the caller of the module that they may not rely on the order of these items, and therefore allows the order to potentially change in future without it being a breaking change to your module.

How do I concatenate an array on strings in ADF Data Flow to a simple string?

I am building an Azure Data Factory. Inside a Data Flow I have an array of strings.
That array of strings I wish to merge into one single string.
ie. [ "value1", "value2" ] into "value1, value2"
Is that even possible, I canĀ“t find any function helping me out here?
I wish there existed a join function or foreach but can't find any?
Here you go:
dropLeft(toString(reduce(['value1','value2','value3','value4'], '', #acc + ', ' + #item, #result)), 2)
Results:
value1, value2, value3, value4
Does toString(myArray) do what you are looking for?
You can use the join function which is present in collection functions in Add dynamic content.
Syntax:
join([<collection>], '<delimiter>')
Example:
join(variables('ARRAY_VARIABLE'), ',')
Refer this to learn more about the Join.
Also, you can do it by using a ForEach loop activity to iterate over the array and use a Set Variable task with a concat expression function to create the comma separated string.
In case, you just have two elements in your array, then you can do like this.
#concat(variables('variable_name')[0].Code1, ',', variables('variable_name')[1].Code1)

Map repeated values in presto

I'm extracting data from JSON and mapping two arrays in presto.It works fine when there are no repeated values in the array but fails with error - Duplicate map keys are not allowed if any of the values are repeated.I need those values and cannot remove any of the values from the array.Is there a work around for this scenario?
Sample values:
array1 -- [Rewards,NEW,Rewards,NEW]
array2 -- [losg1,losg2,losg3,losg4]
Map key/value has to be generated like this [Rewards=>losg1,NEW=>losg2,Rewards=>losg3,NEW=>losg4]
Pairs of associations can be returned like this:
SELECT ARRAY[ROW('Rewards', 'losg1'), ROW('NEW', 'losg2'), ROW('Rewards', 'losg3')]

How to match values in arrays and match result against key/val pair

I'm using Groovy.
I've got two sets of data. The first is an array of site codes and the second is a key/val map of some JSON data.
I need to loop through the list of site codes and match them to key in the map. Once it finds a match it needs to return the corresponding map val.
The map array looks like this:
list = ["WSM-3572", "WSM-0301","WSM-10153"]
A keypair looks like this:
{id=3dd9794a-d148-4f74-a297-cefe22d05cfd, name=Nedbank Mall of Africa(WSM-3572)},{id=8fb57fda-8bdf-4aef-8d50-f3bf8d2235e1, name=Caffe Rossini (WSM-3432)},
{id=bd12b3ef-b72f-4211-8987-2e0c6f1f688d, name=Steers Welkom (WSM-4502)},
So in the above case we should run through the list and when it gets to WSM-3572 it should find it and match the site code in the name: Nedbank Mall of Africa(WSM-3572) and then return id=3dd9794a-d148-4f74-a297-cefe22d05cfd.
I hope this all makes sense and thanks in advance
Assuming you've loaded your json into a map with JsonSlurper, something like
list.each { code ->
println "$code = " + json.find { it ->
it.name.contains "($it)"
}?.id
}
Should do it.
Not at a computer, but that should be close

Resources