Java - Search using a part of key word - java

I have requirement of selecting s subset of data from a collection using a part of a key word
Assume that I have a collection consist of following entries,
"Pine Grosbeak"
"House Crow"
"Hume`s Leaf Warbler"
"Great Northern Loon"
"Long-tailed Duck"
"Lapland Longspur"
"Northern Gannet"
"Eastern Imperial Eagle"
"Little Auk"
"Lesser Spotted Woodpecker"
"Iceland Gull"
When I provide a search string as “ro” following should be filtered;
"House Crow"
"Pine Grosbeak"
(This is something similar to “LIKE ‘%ro%’ “ clause in SQL)
Can some one help me on this?

You could simply do something like that:
for (String s : strings)
{
if (s.contains(search))
{
// match
}
}
And if you want to be case insensitive:
String lowerSearch = search.toLowerCase();
for (String s : strings)
{
if (s.toLowerCase().contains(lowerSearch))
{
// match
}
}

Iterate through and use
contains() method to filter
List<String> lst = new ArrayList<String>();
lst.add("Pine Grosbeak");
lst.add("House Crow");
.
.
.
for(String str:lst){
if(str.contains(keyword)){
System.out.println("matched : "+ str);
}
}

Related

Insert string keyword values based map keys in main string

In Java, I have to insert strings value based on the key in main string.
For example -
Main String -
sellers(seller: $sellerId, shipment: $shipmentId)
Map of key and value -
{
sellerId: abc
shipmentId: 123
}
So after inserting it will become
sellers(seller: abc, shipment: 123)
I know i can do string replace. But that doesn't seem to be good approach here. So just wondering is there a standard approach or better way of doing things here?
Two approaches you can consider:
1 - loop over map entries, and do a simple string replace (note that this assumes a single occurrence of each var in the strings; if that is not the case, you need to use replaceAll):
String text = "sellers(seller: $sellerId, shipment: $shipmentId)";
Map<String, Object> binding = ...;
String result = text;
for (Entry<String, Object> entry : binding.entrySet()) {
result = result.replace("$" + entry.getKey(), String.valueOf(entry.getValue()));
}
2 - for advanced use cases, you want to use a proper template engine. And here's an example using groovy's simple template engine (use in java by adding the groovy jar):
groovy.text.SimpleTemplateEngine engine = new groovy.text.SimpleTemplateEngine();
Writable template = engine.createTemplate(text).make(binding);
String result = template.toString();
Just note that groovy replaces variable names prefixed with $, and that's why this works without changes (making this a good choice for your current syntax).
Both produce your expected result, but you have to choose based on what this can turn into.
Depending on values map can hold you may face some problems. For instance if value may contain other key identifier like
{
foo: $bar
bar: 123
}
then using series of replace(mapEntryKey, mapEntryValue) could change string like
abc $foo efg $bar
first into $foo->$bar
abc $bar efg $bar
and then $bar->123
abc 123 efg 123
which is NOT what we wanted.
To avoid such problem we should iterate over template only once, search for each $key and replace it with value stored for it in map. If map doesn't contain such key we can leave it as it (replace it with itself).
We can do it with Matcher#replaceAll​(Function<MatchResult,​String> replacer). BTW if map value can contain $ and \ which are also metacharacters in replacement, we need to escape them. To do it we can use Mather#quoteReplacement method.
Demo:
Map<String, String> map = Map.of("sellerId", "abc",
"shipmentId", "123");
String yourTemplate = "sellers(seller: $sellerId, shipment: $shipmentId)";
Pattern p = Pattern.compile("\\$(\\w+)");
Matcher m = p.matcher(yourTemplate);
String replaced = m.replaceAll(match -> {
if(map.containsKey(match.group(1))){
return Matcher.quoteReplacement(map.get(match.group(1)));
}else{
return Matcher.quoteReplacement(match.group());
}
});
System.out.println(replaced);
Output: sellers(seller: abc, shipment: 123).
String format is an option here
Map<String, Integer> yourMap = new HashMap<>();
yourMap.put("abc", 123);
for (Map.Entry<String, Integer> entry : yourMap.entrySet()) {
String output = String.format("sellers(seller: %s, shipment: %d)", entry.getKey(), entry.getValue());
System.out.println("output = " + output);
}

Processing HashMap of crew details

Enviroment: Java 7
I have a hashmap 'pdf' of Aircrew details that has the following key structure:
public static Map<String, String> pdf;
PilotName JONES
PilotFirstname Jim
PilotID 12345
PilotLicense AAD987
PilotDOB 12/12/2001
PilotGender Male
PilotEthnicity
PilotAddress 123 Any Street
CopilotName SMITH
CopilotFirstname Thomas
CopilotID 987654
CopilotLicense AAB9475
CopilotAddress 456 Any Street
CopilotDOB 12/03/1987
CopilotGender Male
CopilotEthnicity European
CabinManagerSurname
CabinManagerFirstName BROWN
CabinManagerID 48573
CabinManagerDOB
CabinManagerGender
CabinManagerEthnicity
CabinManagerAddress
Hostess1Surname
Hostess1FirstName
HostessID
Hostess1DOB
Hostess1Gender
Hostess1Ethnicity
Hostess1Address 789 Any Street
Hostess2Surname EDWARDS
Hostess2FirstName Mary
HostessID 475804
Hostess2DOB 11/10/1990
Hostess2Gender Female
Hostess2Ethnicity European
Hostess2Address
Hostess3Surname
Hostess3FirstName
Hostess3ID 489282
Hostess3DOB
Hostess3Gender
Hostess3Ethnicity
Hostess3Address
NB: The field names for crew and pilots are different (Surname/Name Firstname/FirstName).
I want to test if any of certain fields are not empty then call createPerson() method.
The fields to be tested differ for Cabin Crew from Pilots.
I made this attempt but the code is ugly:
List<String> pilotRoles = ["Pilot", "Copilot"];
List<String> cabinRoles = ["CabinManager", "Hostess1", "Hostess2", "Hostess3"];
for (String role : pilotRoles) {
if ( String.isNotNullOrEmpty(pdf.get(pilotRole +"Name")) || String.isNotNullOrEmpty(pdf.get(pilotRole +"Firstname")) || String.isNotNullOrEmpty(pdf.get(pilotRole +"ID")) || String.isNotNullOrEmpty(pdf.get(pilotRole +"License"))) {
listPeople.add(createPerson(pdf, pilotRole));
for (String role : cabinRoles) {
if ( String.isNotNullOrEmpty(pdf.get(cabinRole +"Surname")) || String.isNotNullOrEmpty(pdf.get(cabinRole +"FirstName")) || String.isNotNullOrEmpty(pdf.get(cabinRole +"ID")) ) {
listPeople.add(createPerson(pdf, cabinRole));
For the above data the createPerson routine would be entered for both pilots as at least 1 of the tested fields is not null or empty.
The createPerson routine would NOT be entered for hostess1 and all of the tested fields are null or empty.
Is there a more elegant way? If so how.
I'd try something like this: In addition to your lists of roles, create an additional list that holds the names of all attributes, like "Name" etc.
Then you can then create a function to filter your roles for fields that are missing in your pdf map, like this:
private List<String> getRolesOfMissingUsers(Map<String, String> pdf, List<String> roles, List<String> attributes) {
return roles.stream().filter(role -> attributes.stream().map(attribute -> role + attribute)
.anyMatch(roleAttribute -> StringUtils.isNotBlank(pdf.get(roleAttribute))))
.collect(toList());
}
You can then use the result of this method to create your missing users. Here is an example just for your pilot rules:
for (String role : getRolesOfMissingUsers(pdf, pilotRoles, Arrays.asList("Name", "Firstname", "ID", "License"))) {
listPeople.add(createPerson(pdf, role));
}
EDIT: I noticed you're on Java 7, so you could try this instead:
for (String role : pilotRoles) {
for (String attribute : Arrays.asList("Name", "Firstname", "ID", "License")) {
if (StringUtils.isNotBlank(pdf.get(role + attribute))) {
listPeople.add(createPerson(pdf, role));
break;
}
}
}
If you extract this to a method and pass the list of attributes as a parameter, you should also be able to use this for your crew and pilot list.

Matching a value of HashMap to values in a HashSet

I am trying to match the values of the key in the contextMap to a set of string. I know there is a clear match but despite that I get an empty map in my output. Is it correct to use the contains() method in this case?
The context map contents look like:
[Rhode Island ]=[leftWords: [fellow], rightWords: [solution,
provider]]
And the roleContexts set looks like :
[recent performance, has earned , holdings in , senior vice president
of, solution provider , pharmaceuticals, has launched ]
Here the word solution provider should be a match, thus the key Rhode Island should by put in the output map with he corresponding role (Location in this case).
for(Entry<Set<String>, Set<Words>> entry : contextMap.entrySet()) {
for (String key : entry.getKey()){
for (Words value : entry.getValue()) {
for(SemanticRole role : roleContextsMap.keySet())
{
Set<String> roleContexts = roleContextsMap.get(role);
if(roleContexts.contains(value.getLeftWords().toString().replaceAll("\\[|\\]","").replaceAll(","," ").toLowerCase())
|| roleContexts.contains(value.getRightWords().toString().toString().replaceAll("\\[|\\]","").replaceAll(","," ").toLowerCase()))
{
Set<String> roleStrings = roleStringsMap.containsKey(role)
? roleStringsMap.get(role) : new HashSet<String>();
roleStrings.add(key);
roleStringsMap.put(role, roleStrings);
}
}

Output ArrayList to String without [,] (brackets) appearing

OK, so I have an ArrayList that I need to return as a String. Right now I am using this approach:
List<Customer> customers = new ArrayList<>();
List<Account> accounts = new ArrayList<>();
public String customerList()
{
String list = Arrays.toString(customers.toArray());
return list;
}
public String accountList()
{
String account = Arrays.toString(accounts.toArray());
return account;
}
This works fine, but the problem is that I get brackets around the text. I am getting stuff like:
Customer list:
--------------
[Name: Last, First
, Name: Last, First
, Name: Last, First
]
When I want something like this:
Customer list:
--------------
Name: Last, First
Name: Last, First
Name: Last, First
However, unlike similar questions, I don't simply want to output line by line. I need to store the ArrayList in a String without the brackets so I can work with it.
EDIT: It should be noted that the one comma in the version I want it to look like was placed there by a method in a different class:
public final String getName()
{
return getLast() + ", " + getFirst();
}
EDIT 2: I was able to find a complete solution by adapting the two answers I was given. It was difficult deciding which was the "answer" because I found both useful, but went with the one that I could use more selectively.
public String customerList()
{
String list = Arrays.toString(customers.toArray()).replace(", N", "N").replace(", N", "N");
return list.substring(1,list.length()-1);
}
To remove the brackets I used the modified return. Removing the comma required me to focus on the fact that each line will start with an "N", but the flaw in this approach is that the code would break if I forget to change it here if I change it there. Still, it solves my specific problem, and I can always notate to myself in both places as needed.
You could try to replace the '[' and ']' with empty space
String list = Arrays.toString(customers.toArray()).replace("[", "").replace("]", "");
I think the best solution to print list without brackets and without any separator( for java 8 and higher )
String.join("", YOUR_LIST);
You can also add your own delimiter to separate printing elements.
String.join(", \n", YOUR_LIST);
example above separate each list element with comma and new line.
Java 8 version
List<Integer> intList = new ArrayList<Integer>();
intList.add(1);
intList.add(2);
intList.add(4);
System.out.println(intList.stream().map(i -> i.toString()).collect(Collectors.joining(",")));
Output:
1,2,4
Can directly convert list/set to string and perform action on it
customers.toString().replace("[", "").replace("]", "")
A possible solutions is:
String account = Arrays.toString(accounts.toArray());
return account.substring(1,account.length()-1);
Or do you override the toString method to return the string as per you wanted.
You can use the method substring() to remove starting and ending brackets without tampering any entries in the ArrayList.
I used something like this to convert a ArrayList<String> to String
String str = list.toString().substring(1, list.toString().length() - 1);
If you want your output to look like:
item1, item2, item3
Arrays.toString(customers.toArray()).replace('[', ' ').replace(']', ' ').trim()
If you want your output to look like:
item1 item2 item3
Arrays.toString(customers.toArray()).replace('[', ' ').replace(']', ' ').replace(',', ' ').trim()
You can override the toString() method and represent the output in whatever format you
You can try this.
String listAsStr = myList.toString(); // get list as string
listAsStr = listAsStr.substring(1,listAsStr.length()-1); // removing first and last bracket
This will return the string without first and last brackets.
Anyone still stuck on this, try using a for-each loop.
ArrayList<String> list = new ArrayList<>(); // default size of 10
/*add elements to
the ArrayList*/
for(String element: list)
System.out.println(element);

Data Structure required to store extracted POS tag text in Java

Friends I am doing Sentiment analysis using AANV(adjective-adverb-noun-verb) approach as a my BE final year project. In this project I have done upto the POS tagging, I am using stanford POS Tagger for the same It gives me appropriate result.
for example suppose for the following sentences it gives me output as follows:
Input Sentences:
The camera is worked well.
Camera is very good.
Camera captures photo so slowly.
POS Tagging Output sentences:
The/DT camera/NN is/VBZ worked/VBN well/RB ./.
Camera/NN is/VBZ very/RB good/JJ ./.
Camera/NN captures/VBZ photo/NN so/RB slowly/RB ./.
As above pos tagged output sentences, among that I will required adjective, adverb,noun,verb to be extracted only, with its POS category.
For getting AANV I am using regular expression and write down the following code :
private void btnShowTagActionPerformed(java.awt.event.ActionEvent evt) {
Pattern NounPat=Pattern.compile("[A-Za-z]+/NN");
Pattern AdvPat=Pattern.compile("[A-Za-z]+/RB");
Pattern AdjPat=Pattern.compile("[A-Za-z]+/JJ");
Pattern VerbPat=Pattern.compile("[A-Za-z]+/VB.");
String StrToken;
Matcher mat;
StringTokenizer PosToken;
String TempStr;
int j;
for(int line=0;line<SAPosTagging.tagedReview.length;line++)
{
try{
PosToken=new StringTokenizer(SAPosTagging.tagedReview[line]);
while(PosToken.hasMoreTokens())
{
StrToken=PosToken.nextToken();
mat=NounPat.matcher(StrToken);
if(mat.matches())
{
TempStr=StrToken;
txtareaExTagText.append("Noun=>"+StrToken); //textarea to be appended
j=TempStr.indexOf("/");
TempStr=TempStr.substring(0,j);
System.out.print("\tNoun=>"+TempStr);
}
mat=VerbPat.matcher(StrToken);
if(mat.matches())
{
txtareaExTagText.append("\tVerb=>"+StrToken);
TempStr=StrToken;
j=TempStr.indexOf("/");
TempStr=TempStr.substring(0,j);
System.out.print("\tVerb=>"+TempStr);
}
mat=AdvPat.matcher(StrToken);
if(mat.matches())
{
txtareaExTagText.append("\tAdverb=>"+StrToken);
TempStr=StrToken;
j=TempStr.indexOf("/");
TempStr=TempStr.substring(0,j);
System.out.print("\tAdVerb=>"+TempStr);
}
mat=AdjPat.matcher(StrToken);
if(mat.matches())
{
txtareaExTagText.append("\tAdjective=>"+StrToken);
TempStr=StrToken;
j=TempStr.indexOf("/");
TempStr=TempStr.substring(0,j);
System.out.print("\tAdjective=>"+TempStr);
}
}
System.out.println();
txtareaExTagText.append("\n\n");
}catch(Exception e){}
}
}
with the help of above code I am getting the as below output in my required textarea as follows (i.e. after extracting required tag)
Noun=>camera/NN Verb=>is/VBZ Verb=>worked/VBN Adverb=>well/RB
Noun=>Camera/NN Verb=>is/VBZ Adverb=>very/RB Adjective=>good/JJ
Noun=>Camera/NN Verb=>captures/VBZNoun=>photo/NN Adverb=>so/RB Adverb=>slowly/RB**
Now I want to form the pair as (posword,poscategory) for example (camera,n) so that this pair will be passed to sentiwordnet in order to retrive the score from the Sentiwordnet. Please give me code for storing this pair structure without disurbing sentences link or structure so that i will passed it to sentiwordnet.
While forming pair the sentences structure should be maintained. It may happened that one sentence contains multiple verbs, nouns, adverbs or adjective.
I advice you to forget about 'data structure' and model it thinking about OO classes. Think about a Sentence class and what do you want to store about a sentence and how to store Sentences.
If you insist on using 'general' data structures you may use a List where every element represents a sentence with type Guava's Multimap.
The key would be Noun/Verb/Etc and the value would be the word. It allows several values per key.
Reference here.
Guava example (not tested):
List<Multimap<String, String>> sentenceList = new ArrayList<>();
for (String line: lines) {
Multimap<String, String> aux = ArrayListMultimap.create();
PosToken=new StringTokenizer(SAPosTagging.tagedReview[line]);
while(PosToken.hasMoreTokens()) {
// TODO ...
strToken=PosToken.nextToken();
// TODO, lets assume it is a noun
aux.put("noun", strToken);
// TODO, etc.
}
sentenceList.add(aux);
}
OO example (not tested):
public class Sentence {
private List<String> nouns = new ArrayList<>;
private List<String> verbs = new ArrayList<>;
// TODO Adverbs, etc.
public List<String> getNons() { return nouns; };
// TODO Other getters, etc.
}
List<Sentence> sentenceList = new ArrayList<>();
for (String line: lines) {
Sentence aux = new Sentence();
PosToken=new StringTokenizer(SAPosTagging.tagedReview[line]);
while(PosToken.hasMoreTokens()) {
// TODO ...
strToken=PosToken.nextToken();
// TODO, lets assume it is a noun
aux.getNouns().add(strToken);
// TODO, etc.
}
sentenceList.add(aux);
}

Categories