Extract string from a long string in scala - regex

I want to extract the useful fields from a string object like the following one
Request(Some(8454439),Some(16872692),Some(0.0.0.0),Some(8281008),Some(ArrayBuffer(845434399)),Some(129032),Some(3),Some(Profile),Some(en),None,None,None,None,Some(true),None,Some(Food),None,Some(Fish))
It has 18 fields in total, and what I want to do is assign them to 18 different strings and extract useful info if it is Some(X), otherwise set the string to None.
For example in this case, the string array in the response should be
val results = Array("8454439", "16872692", "0.0.0.0", "8281008", "ArrayBuffer(845434399)",
"129032", "3", "Profile", "en", "None", "None", "None", "None", "true", "None",
"Food", "None", "Fish")

If you can get the list of items somehow, you could do something like this with a Seq[Option[Any]]:
val items: Seq[Option[Any]] = ???
items.map(_.getOrElse("None").toString)
But if you only have the output of Request.toString, this will get you most of the way there:
val s = "Request(Some(8454439),Some(16872692),Some(0.0.0.0),Some(8281008),Some(ArrayBuffer(845434399)),Some(129032),Some(3),Some(Profile),Some(en),None,None,None,None,Some(true),None,Some(Food),None,Some(Fish))"
val pat1 = """Some\([\w.()]+?\)|None""".r
val pat2 = """Some\((.*)\)""".r
pat1.findAllIn(s).map {
case pat2(some) => some
case x => x
}.toList
// res0: List[String] = List(8454439, 16872692, 0.0.0.0, 8281008, ArrayBuffer(845434399, 129032, 3, Profile, en, None, None, None, None, true, None, Food, None, Fish)
My regex-fu isn't strong enough to keep the trailing parenthesis on the ArrayBuffer value, but otherwise this seems to work.

Have you tried something along the lines of
val items = request.map {
case Some(value) => value
case None => "None"
}
To actually convert Some(ArrayBuffer(845434399)) to "ArrayBuffer(845434399)" though, you may need a nested match statement:
val items = request.map {
case Some(value) => value match {
case strng: String => strng
case other => ???
}
case None => "None"
}
Off the top of my head, not sure what to call to do it, but maybe one of the functions of the Any type would be of help.

Related

how to create a filter to search for a word with special characters while writing in the input without special characters

it's my first post.
I work to Quasar (Vue.js)
I have list of jobs, and in this list, i have words with special caractere.
Ex :
[ ...{ "libelle": "Agent hôtelier" },{"libelle": "Agent spécialisé / Agente spécialisée des écoles maternelles -ASEM-"},{ "libelle": "Agriculteur / Agricultrice" },{ "libelle": "Aide aux personnes âgées" },{ "libelle": "Aide de cuisine" },...]
And on "input" i would like to search "Agent spécialisé" but i want to write "agent specialise" (without special caractere) or the initial name, i want to write both and autocomplete my "input".
I just don't fin the solution for add to my filter code ...
My input :
<q-select
filled
v-model="model"
use-input
hide-selected
fill-input
input-debounce="0"
:options="options"
hint="Votre métier"
style="width: 250px; padding-bottom: 32px"
#filter="filterFn"
>
</q-select>
</div>
My code :
export default {
props: ['data'],
data() {
return {
jobList: json,
model: '',
options: [],
stringOptions: []
}
},
methods: {
jsonJobsCall(e) {
this.stringOptions = []
json.forEach(res => {
this.stringOptions.push(res.libelle)
})
},
filterFn(val, update) {
if (val === '') {
update(() => {
this.jsonJobsCall(val)
this.options = this.stringOptions
})
return
}
update(() => {
const regex = /é/i
const needle = val.toLowerCase()
this.jsonJobsCall(val)
this.options = this.stringOptions.filter(
v => v.replace(regex, 'e').toLowerCase().indexOf(needle) > -1
)
})
},
}
}
To sum up : i need filter for write with or witouth special caractere in my input for found in my list the job which can contain a special character.
I hope i was clear, ask your questions if i haven't been.
Thanks you very much.
I am not sure if its work for you but you can use regex to create valid filter for your need. For example, when there is "e" letter you want to check "e" or "é" (If I understand correctly)
//Lets say we want to match "Agent spécialisé" with the given search text
let searchText = "Agent spe";
// Lets create a character map for matching characters
let characterMap = {
e: ['e', 'é'],
a: ['a', '#']
}
// Replacing special characters with a regex part which contains all equivelant characters
// !Remember replaceAll depricated
Object.keys(characterMap).forEach((key) => {
let replaceReg = new RegExp(`${key}`, "g")
searchText = searchText.replace(replaceReg, `[${characterMap[key].join("|")}]`);
})
// Here we create a regex to match
let reg = new RegExp(searchText + ".*")
console.log("Agent spécialisé".match(reg) != null);
Another approach could be the reverse of this. You can normalize "Agent spécialisé". (I mean replace all é with normal e with a regex like above) and store in the object along with the original text. But search on this normalized string instead of original.

Obtain values that match from several conditions on a list in javascript

I'm trying to obtain a list from a list in Javascript.
This is the list:
const cars = [
{
id: 1,
brand: "Mercedes Benz",
properties: [
{
property: "Mechanical",
value: 2,
},
{
property: "Chemical",
value: 2,
},
{
property: "Pressure",
value: 3,
}],
},
{
id: 2,
brand: "BMW",
properties: [
{
property: "Mechanical",
value: 5,
},
{
property: "Chemical",
value: 3,
},
{
property: "Pressure",
value: 6,
}],
}
]
I need the cars which match some properties property with a value greater than X, Y
For example, I want the cars which Mechanical properties have a value greater than 3 and a Pressure greater than 4. In that case I'll obtain the complete object with id 2.
Does anyone have an idea? That is having me a hard time
Tip: I paste it on a Node REPL ;)
This is what I tried but I obtain nothing:
cars.filter(car => car.properties.some((p1, p2) => {return ((p1.property === "Mechanical" && p1.value > 3) && (p2.property === "Pressure" && p2.value > 4))}))
Thanks in advance
You need to iterate all items and check each one for it's relevant condition, and if all items pass, return true. In your case you are checking each item for all conditions, and since no item's property can have both "Mechanical" and "Pressure" values at the same time, all fail.
When an array needs to pass all conditions, you should use Array.every() that will only return true, if all iterated items would return true.
To make this more generic, we can store the conditions as functions in an object or a Map. If there is a condition function for this property, we'll use the function to check the value. If not, we can return true immediately.
Note: this answer uses Optional chaining (?.) and the Nullish coalescing operator (??) to return true if the predicate doesn't exist. If your running environment doesn't support this operators replace the line with predicate[property] ? predicate[property](value) : true (see 2nd example).
const fn = (predicate, cars) =>
cars.filter(car => car.properties.every(({ property, value }) =>
predicate[property]?.(value) ?? true
))
const cars = [{"id":1,"brand":"Mercedes Benz","properties":[{"property":"Mechanical","value":2},{"property":"Chemical","value":2},{"property":"Pressure","value":3}]},{"id":2,"brand":"BMW","properties":[{"property":"Mechanical","value":5},{"property":"Chemical","value":3},{"property":"Pressure","value":6}]}]
const predicate = {
Mechanical: value => value > 3,
Pressure: value => value > 4,
}
const result = fn(predicate, cars)
console.log(result)
Or using a ternary:
const fn = (predicate, cars) =>
cars.filter(car => car.properties.every(({ property, value }) =>
predicate[property] ? predicate[property](value) : true
))
const cars = [{"id":1,"brand":"Mercedes Benz","properties":[{"property":"Mechanical","value":2},{"property":"Chemical","value":2},{"property":"Pressure","value":3}]},{"id":2,"brand":"BMW","properties":[{"property":"Mechanical","value":5},{"property":"Chemical","value":3},{"property":"Pressure","value":6}]}]
const predicate = {
Mechanical: value => value > 3,
Pressure: value => value > 4,
}
const result = fn(predicate, cars)
console.log(result)

customized sorting using search term in django

I am searching a term "john" in a list of dict ,
I have a list of dict like this :
"response": [
{
"name": "Alex T John"
},
{
"name": "Ajo John"
},
{
"name": "John",
}]
I am using :
response_query = sorted(response, key = lambda i: i['name'])
response_query return ascending order of result only but I need a result with first name as a priority.
Expected result:
{
"name": "John"
},
{
"name": "Ajo John"
},
{
"name": "Alex T John",
}
The first name containing search term should appear first.
If you need to sort with priorities you can try a key-function that returns tuple. In your particular case, as far as I got the question, this function will work fine:
response_query = sorted(
response,
key=lambda i: (len(i['name'].split()) > 1, i['name'])
)
In other words, I added the condition len(i['name'].split()) > 1 that return False (it will go first) if the name consists of one word only, else True.
For the case, if you need the priority condition as the name starts with the term you used in the search, the result would be:
term = 'john'
...
response_query = sorted(
response,
key=lambda i: (not i['name'].lower().startswith(term), i['name'])
)

groovy: create a list of values with all strings

I am trying to iterate through a map and create a new map value. The below is the input
def map = [[name: 'hello', email: ['on', 'off'] ], [ name: 'bye', email: ['abc', 'xyz']]]
I want the resulting data to be like:
[hello: ['on', 'off'], bye: ['abc', 'xyz']]
The code I have right now -
result = [:]
map.each { key ->
result[random] = key.email.each {random ->
"$random"
}
}
return result
The above code returns
[hello: [on, off], bye: [abc, xyz]]
As you can see from above, the quotes from on, off and abc, xyz have disappeared, which is causing problems for me when i am trying to do checks on the list value [on, off]
It should not matter. If you see the result in Groovy console, they are still String.
Below should be sufficient:
map.collectEntries {
[ it.name, it.email ]
}
If you still need the single quotes to create a GString instead of a String, then below tweak would be required:
map.collectEntries {
[ it.name, it.email.collect { "'$it'" } ]
}
I personally do not see any reasoning behind doing the later way. BTW, map is not a Map, it is a List, you can rename it to avoid unnecessary confusions.
You could convert it to a json object and then everything will have quotes
This does it. There should/may be a groovier way though.
def listOfMaps = [[name: 'hello', email: ['on', 'off'] ], [ name: 'bye', email: ['abc', 'xyz']]]
def result = [:]
listOfMaps.each { map ->
def list = map.collect { k, v ->
v
}
result[list[0]] = ["'${list[1][0]}'", "'${list[1][1]}'"]
}
println result

Sort depending on variable in Scala

Is there any way in Scala to sort a list of objects by a specific field using a variable to set the order (ASC or DESC)?
I know with sortWith you can do something like
myList.sortWith((x, y) => x < y)
or
myList.sortWith((x, y) => x > y)
to sort ascending or descending, but I want to use a variable.
So, I tried something like this:
case class Person(firstName: String, LastName: String, age: Int)
private def sortDocuments(sortField: String, sortDirection: String, people: List[Person]): List[Person] = {
sortField match {
case "age" => people.sortBy(if (sortDirection == "desc") -_.age else _.age)
case "firstName" => people.sortWith { sortString(a.firstName, b.firstName, sortDirection) }
case "lastName" => people.sortWith { sortString(a.firstName, b.lastName, sortDirection) }
}
}
private def sortString(fieldA: String = null, fieldB: String = null, direction: String = "asc") = {
val fieldAVaild = Option(fieldA).getOrElse("")
val fieldBVaild = Option(fieldB).getOrElse("")
if (direction == "desc") fieldBVaild > fieldAVaild else fieldAVaild < fieldBVaild
}
But sortWith only receives a function with two parameters, so I get an error when I add the third parameter (sortDirection).
You forgot the (a, b) => expr part of the first/last name cases
case "firstName" => people.sortWith {(a, b) => sortString(a.firstName, b.firstName, sortDirection) }