Groovy - insert string in every last entry of group - list

Original List:
def list = [[category: "DLF", name: "some name one"],
[category: "EF", name: "some name two"],
[category: "RW", name: "some name five"],
[category: "EF", name: "some name four"],
[category: "DLF", name: "some name two"],
[category: "RW", name: "some name three"]]
Is there a way to group it by category and sort it by category but is should be exactly arrange as "EF", "DLF", "RW" and I also want to insert new element in every last index of the category just like this one:
def list = [[category: "EF", name: "some name two"],
[category: "EF", name: "some name four"],
[category: "EF", name: "others"],
[category: "DLF", name: "some name one"],
[category: "DLF", name: "some name two"],
[category: "DLF", name: "others"],
[category: "RW", name: "some name three"],
[category: "RW", name: "some name five"],
[category: "RW", name: "others"]]

So you can define the order you want the results in:
def requiredOrder = ['EF', 'DLF', 'RW']
Then, you can group, sort, and add the others element:
def result = list.groupBy { it.category }
.sort { requiredOrder.indexOf(it.key) }
.collectMany { k, v -> v + [category: k, name: 'others'] }
The required result will be in the variable result

Almost the same as from #tim_yates, but slightly more straight-forward:
def requiredOrder = ['EF', 'DLF', 'RW']
def result = ( list + requiredOrder.collect{ [ category:it, name: "others"] } )
.sort{ requiredOrder.indexOf it.category }

Related

Lazy match Node regex over multiple lines

I'm trying to parse a bunch of javascript files and pull out certain objects. an example of the file would be:
import { foo } from "blah";
import { bar, baz } from "../module";
const myobject = {
name: NAME,
title: {
name: `${NAME}.title`,
defaultMessage: "title",
},
description: {
name: `${NAME}.description`,
defaultMessage: "description",
},
property: 'stringvalue',
};
const anotherObject = {
name: `${NAME}.other`,
defaultMessage: "other",
}
I need to pull out all the objects that have the property "defaultMessage". For the matcher I have:
/\{([\s\S]*?)defaultMessage([\s\S]*?)\}/g
This is matching anotherObject and myobject.description correctly, but for myobject.title it's getting everything from the first { before foo. e.g:
{ foo } from "blah";
import { bar, baz } from "../module";
const myobject = {
name: NAME,
title: {
name: `${NAME}.title`,
defaultMessage: "Main",
}
How can I get this to lazy match further so I only get:
{
name: `${NAME}.title`,
defaultMessage: "Main",
}
Update: I'll be using node to parse the javascript files, so I get access to negative look behinds, I tried the following with no luck:
(?<!\{[\s\S]+?)\{([\s\S]+?)defaultMessage([\s\S]*?)\}
I would not use this in any production code but this would work for your case:
([a-zA-Z]*?)(?:\s=|:)\s(\{(?:(?!([a-zA-Z]*?)(\s=|:)\s\{)[\s\S])*?defaultMessage(?:[\s\S]*?)\})
I added ([a-zA-Z]*?)(\s=|:)\s, so that we only capture the opening bracket if it is prefixed by xyZ = or `abC:'.
Also added a negative lookahead so that the pattern doesn't repeat itself:
(?!([a-zA-Z]*?)(\s=|:)\s\{)
Furthermore I added some non capturing groups in order to decrease regex group clutter if you intend to use this in some code. For example this regex captures:
title: {
name: `${NAME}.title`,
defaultMessage: "title",
}
With title as sub group 1
and:
{
name: `${NAME}.title`,
defaultMessage: "title",
}
As subgroup 2, you can approach subgroup 2 in order to get your desired capture.
Alternatively use:
(?=[a-zA-Z]*?)\{(?:(?!([a-zA-Z]*?)(\s=|:)\s\{)[\s\S])*?defaultMessage(?:[\s\S]*?)\}
To only capture:
{
name: `${NAME}.title`,
defaultMessage: "title",
}
With no subgroups

DynamoDB overriding existing key value pair due to AttributeValues

----------------- GIVING MORE CONCRETE EXAMPLES BELOW -----------------
I have the following function, where I take user, name, sex from parameters and update the existing client for that user.
function createRecord(user, personName, sex) {
var sexPayload = [];
var dynamoParams = {
TableName: 'account',
Key: {
id: user
},
UpdateExpression: "set #client.#person.#sex = :sexPayload",
ExpressionAttributeNames: {
"#client": "client",
"#person": personName,
"#sex": sex
},
ExpressionAttributeValues: {
":sexPayload": sexPayload,
},
ConditionalExpression: "attribute_not_exists(#client.#person.#sex)"
};
docClient.update(dynamoParams, function(err, data){
something...
});
}
if personName = "John" sex = "man",
this creates
client: {
John: {"M": {"man": {"L": []}}},
}
and when I pass in another name = "John" sex = "female",
this overrides existing John "man" and writes "female" under John
client: {
John: {"M": {"female": {"L": []}}},
}
What I want to achieve is this:
client: {
John: {"M": {"man": {"L": []}, {"female": {"L": []}},
}
what am I doing wrong??

Fn::Sub expression does not resolve to a string

I have created a parameter:
Parameters:
..
list:
Description: "Provide a list .."
Type: CommaDelimitedList
Default: "test1, test2"
Now I want to reference this list (which will resolve in "test1", "test2", ..) from a file in my cloudformation which looks like this:
configure_xx:
files:
/etc/file.conf:
content: !Sub |
input {
logs {
log_group => [ "${list}" ]
access_key_id => "${logstashUserKey}"
secret_access_key => "${logstashUserKey.SecretAccessKey}"
region => "eu-west-1"
}
}
How can I make this work for the parameter list? (the keys work).
error: Fn::Sub expression does not resolve to a string
Just switch the parameter type for a "String"
Parameters:
..
list:
Description: "Provide a list .."
Type: String
Default: "test1, test2"
If, for some reason, you have no control over this parameter type, you could use Fn::Join to transform the list to a string. For exemple:
configure_xx:
files:
/etc/file.conf:
content:
Fn::Sub:
- |-
input {
logs {
log_group => [ "${joinedlist}" ]
access_key_id => "${logstashUserKey}"
secret_access_key => "${logstashUserKey.SecretAccessKey}"
region => "eu-west-1"
}
}
- joinedlist:
Fn::Join:
- ', '
- !Ref list

How to use if condition in Karate

Suppose I have the following Json response
[
{
id: 1,
name: "John",
password: "JohnsPassword54",
},
{
id: 2,
name: "David",
password: "DavidsPassword24",
}
]
Then how can I extract the array with name David to do further validation?
e.g. I want to say if name == David then save the id
Well done :) Mastering Json-Path is key to get the most out of Karate !
Just for the sake of demo, here is another option, using the get keyword to get the first element out of the array returned, as Json-Path wildcard searches always return an array:
* def response =
"""
[
{
id: 1,
name: "John",
password: "JohnsPassword54"
},
{
id: 2,
name: "David",
password: "DavidsPassword24"
}
]
"""
* def userId = get[0] response $[?(#.name == 'David')].id
* match userId == 2
I found the solution in the Json expression evaluation -
def user = $..[?(#.name == 'David')]
Then I can use the following -
def userId = user[0].id

mongoid adding additional results to a query

So in Mongoid, I am sending as JSON a series of custom report templates. But the client also has some report types, which are always included.
So a User has many Groups and each group has many ReportTemplates
So when I run #user.report_templates I am given a hash like so ->
id: "the-snake-report"
name: "The Snake Report"
icon: null
location: null
active: "2014-06-20"
-field_templates: [
-{
-_id: {
$oid: "5391794d4d6163fcea360000"
}
mandatory: false
name: "How long was it?"
options: null
}
-{
-_id: {
$oid: "5391794d4d6163fcea370000"
}
mandatory: false
name: "Did it have any legs?"
options: null
}
-{
-_id: {
$oid: "5391794d4d6163fcea380000"
}
mandatory: false
name: "Did it any languages?"
-options: [
"English"
"Spanish"
"French"
]
}
]
}
-{
id: "bad-kids"
name: "Bad kids "
icon: null
location: null
active: "2014-06-19"
-field_templates: [
-{
-_id: {
$oid: "539167714d6163fcea2b0000"
}
mandatory: false
name: "fish"
-options: [
"one"
"two"
"three"
]
}
-{
-_id: {
$oid: "539167714d6163fcea2c0000"
}
mandatory: false
name: "The cat in the hat?"
options: null
}
-{
-_id: {
$oid: "539167714d6163fcea2d0000"
}
mandatory: true
name: "Are you ok?"
options: null
}
-{
-_id: {
$oid: "539167714d6163fcea2e0000"
}
mandatory: true
name: "Is it a house?"
-options: [
"A car"
"a boat"
]
}
]
}
etc.
So I would like to take that method such as #user.report_templates.includes(ReportTemplate.simple_report)
and have it include onto that hash. (Instead of keeping it in the DB, I would prefer to keep it as a method)
But I am not really sure what to do with the error:
TypeError: wrong argument type Hash (expected Module)
So I have also tried to make a helper (module) called SimpleReport
#user.report_templates.includes(ReportTemplate.simple_report)
But then I get a MOPED query
Thank you for helping.
Ok So I figured it out.
Basically taking the results.to_json and appending onto it my results.
render json: #template.as_json << ReportTemplate.simple_report