Map with optional variables as Keys and multiple if elseif condition - java

Need your help because I'm overthinking a bit. :P
I'm doing a development in apex where we build a Map based on certain keys. Those keys are a mix of multiple variables and so when building a map we have something like:
for(rule){
key = String.isBlank(rule.CompanyRisk) ? '' : rule.CompanyRisk;
key += String.isBlank(rule.PriceType) ? '' : rule.PriceType;
key += String.isBlank(rule.Product) ? '' : rule.Product;
key += String.isBlank(rule.CompanySize) ? '' : rule.CompanySize;
//..
map.put(Key, rule.Value);
}
return map;
//and later to get the correct value
for(offerRecord){
String accRisk = offerRecord.CompanyRisk;
String price = offerRecord.PriceType;
String product= offerRecord.Product;
String accSize = offerRecord.CompanySize;
if(map.contains(accRisk + price + product + accSize)){
key = accRisk + price + product + accSize;
}else if(map.contains( accRisk + price + product + '')){
key = accRisk + price + product + '';
}else if(map.contains(accRisk + price + '' + accSize)){
key = accRisk + price + '' + accSize,
}else if.. //16 conditions now (4 variables as optional)
}
return map.get(key);
Issue:
Some fields on the key are optional and that happens so the users dont need to create all the rules for all the combinatorions. and when those optional fields are empty/null it's because it applies for all values of the field.
Example: We can have a rule as (LowRisk + Indexed + Computer + Small) with Value=4 and a rule for (Low + Indexed + Computer + '' ) with Value=5 , meaning if the company is small applies the 1st rule but if it it's medium/big/top it applies the one without. Same for the other fields. I can have just one saying (HighRisk + + +) with a value of 0 without the need of specifying all the other criteriums and it applies for all of them.
Because we need to always checking first rules/keys with the optional fields filled, it will become a mess due to a lot of if else.
The conditions are like (ABCD, ABC, ABD, AB, ACD, AC, AD, A, BCD, BC, BD, B, CD, C, D ,'' )
Is there any better solution that could improve this?
I was trying now building some Wrapper class that would return a List for the all combinations and then have a specific method getRuleForRecord() which based on the List (ordered) creates a key from the values of record and checks if map has that key. Not a much prettier aproach. The worst now is building the listOfCombinations on the order I want
List<String> keyList = singleton.listOfCombinations;
for (String fieldList : keyList) {
String mapKey = '';
for (String field : fieldList.split('_')) {
mapKey += recordToGetInfoFrom.get(field);
}
if (singleton.ruleMap.containsKey(mapKey)) {
return singleton.remRules.get(mapKey);
}
}

Related

HashMap: Match a string with a value if it contains part of the string?

I have a text file, which is filled with many lines of code in the layout: "fiesta, ford". I read these lines with new BufferedReader(new InputStreamReader(...)) and then I display them in my app.
This method findCar() takes an input, compares it with the keys of the hashmap which are taken from the text file, and if it matches, it displays the car model and the card brand in another layout part :). What is for example: Is there a possibility to make my code a little more advanced? Let's say that the user types Fiesta 2018, or Fiesta 2019. I want it to be accepted. So I want to say that if the given string contains "Fiesta", match it with "ford" and display them. I don't know how to make it work for every other brand, and i don't want to have 100 if statements.
I am sorry for the rookie question, I have tried many many versions like else if(car.equalsIgnoreCase(carItem.getKey())){ but I can't make it work.
public String findCar(String car) {
String x = "";
for (HashMap.Entry<String, String> carItem: itemsMap.entrySet()) {
if (carItem.getKey().equalsIgnoreCase(car)){
x = x + "Found " + carItem.getKey() + " in:" + carItem.getValue();
return x;
}
}
return "Sorry, not found :D";}
You should try following code (use "contains" function and convert to one case both strings) :
public String findCar(String car) {
String carLowerCase = car.toLowerCase().trim();
String x = "";
for (HashMap.Entry<String, String> carItem: itemsMap.entrySet()) {
String key = carItem.getKey().toLowerCase().trim();
if (carLowerCase.contains(key)){
x = x + "Found " + carItem.getKey() + " in:" + carItem.getValue();
return x;
}
}
return "Sorry, not found :D";
}
You want to refine your keyword.
For example, in the
Fiesta 2018
you only need the Fiesta part. So it makes sense say if the last four letters are digits, you simply remove it.
For example:
Map<String,String> modelBrand = new HashMap<>();
String keyword = "Fiesta 2018";
String[] keys = keyword.split(" [0-9]{4}");
if(keys.length > 0) {
keyword = keys[0];
}
// Print not found since nothing in the map.
System.out.println(modelBrand.getOrDefault(keyword.toLowerCase(), "Not found"));
modelBrand.put("fiesta", "ford");
// Print ford as it finds the fiesta keyword.
System.out.println(modelBrand.getOrDefault(keyword.toLowerCase(), "Not found"));
A better way to do it is utilize a search engine, such as the open source solr.

Java: Issue when replacing Strings on loop

I'm building a small app which auto translates boolean queries in Java.
This is the code to find if the query string contains a certain word and if so, it replaces it with the translated value.
int howmanytimes = originalValues.size();
for (int y = 0; y < howmanytimes; y++) {
String originalWord = originalValues.get(y);
System.out.println("original Word = " + originalWord);
if (toReplace.contains(" " + originalWord.toLowerCase() + " ")
|| toCheck.contains('"' + originalWord.toLowerCase() + '"')) {
toReplace = toReplace.replace(originalWord, translatedValues.get(y).toLowerCase());
System.out.println("replaced " + originalWord + " with " + translatedValues.get(y).toLowerCase());
}
System.out.println("to Replace inside loop " + toReplace);
}
The problem is when a query has, for example, '(mykeyword OR "blue mykeyword")' and the translated values are different, for example, mykeyword translates to elpalavra and "blue mykeyword" translates to "elpalavra azul". What happens in this case is that the result string will be '(elpalavra OR "blue elpalavra")' when it should be '(elpalavra OR "elpalavra azul")' . I understand that in the first loop it replaces all keywords and in the second it no longer contains the original value it should for translation.
How can I fix this?
Thank you
you can sort originalValues by size desc. And after that loop through them.
This way you first replace "blue mykeyword" and only after you replace "mykeyword"
The "toCheck" variable is not explained what is for, and in any case the way it is used looks weird (to me at least).
Keeping that aside, one way to answer your request could be this (based only on the requirements you specified):
sort your originalValues, so that the ones with more words are first. The ones that have same number of words, should be ordered from more length to less.

Retrieval of synonyms of an instance from whole ontology

Individual ind = model.createIndividual("http://www.semanticweb.org/ontologies/Word#Human", isSynonymOf);
System.out.println( "Synonyms of given instance are:" );
StmtIterator it =ind.listProperties(isSynonymOf);
while( it.hasNext() ) {
Statement stmt = ((StmtIterator) it).nextStatement();
System.out.println( " * "+stmt.getObject());
}
Output
Synonyms of given instance are:
http://www.semanticweb.org/ontologies/Word#Human
http://www.semanticweb.org//ontologies/Word#Mortal
http://www.semanticweb.org/ontologies/Word#Person
Problem 1: My output shows whole URI but I need output as under
Synonyms of given instance are:
Human
Mortal
Person
Problem 2: I have 26 instances and every time I have to mention its URI to show its synonyms. How will I show synonyms of any instance from whole ontology model instead of mentioning URIs again and again. I am using eclipse Mars 2.0 and Jena API
You can use REGEX or simply Java string operations to extract the substring after #. Note, best practice is to provide human readable representations of URIs and not to encode it in the URI. For instance, rdfs:label is a common property for doing that.
It is simply iterating over all individuals of the ontology which are returned by
model.listIndividuals()
Some comments:
You're using the method createIndividual not as expected. The second argument denotes a class and you're giving it a property. Please use Javadoc for the future.
I don't understand why you're casting it to StmtIterator - that doesn't make sense
Using listPropertiesValues is more convenient since you're only interested in the values.
Use Java 8 to make the code more compact
model.listIndividuals().forEachRemaining(ind -> {
System.out.println("Synonyms of instance " + ind + " are:");
ind.listPropertyValues(isSynonymOf).forEachRemaining(val -> {
System.out.println(" * " + val);
});
});
Java 6 compatible version:
ExtendedIterator<Individual> indIter = model.listIndividuals();
while(indIter.hasNext()) {
Individual ind = indIter.next();
System.out.println("Synonyms of instance " + ind + " are:");
NodeIterator valueIter = ind.listPropertyValues(isSynonymOf);
while(valueIter.hasNext()) {
RDFNode val = valueIter.next();
System.out.println(" * " + val);
}
}

Replacing certain characters in java

I have a SQL query passed to me in a text, here is a part of it:
WHERE
(t.STIME > CAST(SYSTIMESTAMP AS TIMESTAMP) + NUMTODSINTERVAL(-86400000 * 0.001, 'SECOND'))
) t ORDER BY
m_2 ASC, m_1 ASC, t.STIME ASC
What I want to do, is to simply modify it in a way that I will have:
WHERE
(t.STIME > CAST(SYSTIMESTAMP AS TIMESTAMP) + NUMTODSINTERVAL(-86400000 * 0.001, 'SECOND'))
ORDER BY
m_2 ASC, m_1 ASC, t.STIME ASC )
So, I need to somehow remove: ") t" from within the String, but how to do that? I always receive "unmatched ')' parenthesis and I really don't know why x/
Here is a method I wrote for replacing this string:
public static String replaceLast(String string, String toReplace, String replaceWith) {
int last = string.lastIndexOf(toReplace);
if (last < 0) return string;
String ending = string.substring(last).replaceFirst(toReplace, replaceWith);
return string.substring(0, last) + tail;
}
then I'm trying to use it this way:
if(sqlToTrim.lastIndexOf("\\) t") > 0){
replaceLast(sqlToTrim, "\\) t ", " ");
addLastParanthesis(sqlToTrim);
}
But it is not replaced, basicly nothing changes - replaceLast is never used. I assume I messed up with regex, I searched through stack overflow but it seems \ is the right combination that I should put before ). Thanks in advance for your help. Could anyone tell me what am I doing wrong?
If you need to know, why do I do that, why in this way - legacy code...
Strings are immutable. replaceLast(sqlToTrim, "\\) t ", " "); returns a new string. Do:
sqlToTrim = replaceLast(sqlToTrim, "\\) t ", " ");
and continue on from there. If addLastParenthesis modifies the string it should return it, i.e.
sqlToTrim = replaceLast(sqlToTrim, "\\) t ", " ");
sqlToTrim = addLastparenthesis(sqlToTrim);

Map entry key in java

I'm trying to debug a problem I've on a script, I'm newly to Java I think it's a simplest thing but I need to understand. This :
for( Map.Entry<String,int[]> entry : this.indexMap.entrySet())
{
if( !entry.getKey().equals("nickname"))
{
System.out.print("'"+ entry.getKey() +"' contains "+ entry.getKey().length() +" chars");
System.out.print("'"+ name +"' contains "+ name.length() +" chars");
}
else if( entry.getKey().trim().equals("nickname") )
{
System.out.print("Yes are sames");
}
}
For a String name = "nickname", displays me that :
18:56:15 [INFOS] 'nickname' contains 94 chars
18:56:15 [INFOS] 'nickname' contains 8 chars
I'm trying to understand this.
The problem is entry.getKey() returns the same thing as my string name, but not really the same. In first test, we saw the two vars are different, so the print is did, but the twos vars have the same value, and not the same length. In the else-if, I tried to remove spaces but not printed so where are from these 94 chars?
https://code.google.com/p/imdbparsers/source/browse/trunk/imdb+parsers/src/imdb/parsers/xmltosql/NamedParameterStatement.java?r=6
Is the code, methods concerned are
private String parse(String query)
private int[] getIndexes(String name)
line 161 et 89
This for loop i've in mine is only to debug the
int[] indexes = (int[]) indexMap.get(name);
Returns always null
The query string is :
SELECT COUNT(`account_id`) AS `total` FROM `game_accounts` WHERE `nickname`=:nickname
The difference between
entry.getKey().equals("nickname")
and
entry.getKey().trim().equals("nickname")
is trim().
The first take in account the spaces and the second not.
It's because they are a loop on a map: to find the 'bad' keys...
I think that if you reverse your if clauses you might get something that behaves more like what you are expecting, although it is somewhat unclear what you are asking. Comparing keys as the first clause in the if block makes the code simpler.
if( entry.getKey().trim().equals("nickname") )
{
System.out.print("Yes are sames");
}
else
{
System.out.print("'"+ entry.getKey() +"' contains "+ entry.getKey().length() +" chars");
System.out.print("'"+ name +"' contains "+ name.length() +" chars");
}

Categories