I'm new to Android. Currently I'm working on a quiz using SpeechRecognizer to choose the answer of the question
answer has 5 radio button
each radio has 3 to 5 words
Answer example:
Jhonny likes an apple
Donny likes an apple
Boni likes an apple
Ronney likes an apple
Molly likes an apple
Currently my App can only select the answer if the recognized words are all matched.
what i want to do is..
how can my App select one of the answer, if recognized word is more than other.
just like this, if recognized word is Molly and apple, so the closest answer is Molly likes an apple, then my app can select it.
How can i accomplish this?
Thankyou in advance.
To make it work well, you have to do some workaround. My advices are:
to choose names, which are totally different from each other. Like: Johnny, Steven, Alfred, etc. The reason is to make sure the name will be picked up correctly and Bonny won't be mixed with Johnny.
when you have the properly chosen names, collect the recognition result for all of the names (johnny, jonny, johnnie, johny, jonnie) and create separate array or list from these
to handle these you use them as constant list or create map, according to your programming style
When you are processing the recognition result, i suggest to brake all of the results into words, so you can compare them with the expected answers.
public void onResults(Bundle results){
...
//this is your predefined name synonyms
List<String> johnnyNameList = (ArrayList<String>);
johnnyNameList.add("johnny");
johnnyNameList.add("jonny");
johnnyNameList.add("johnnie");
List<String> katieNameList = (ArrayList<String>);
katieNameList.add("katy");
katieNameList.add("katie");
katieNameList.add("kattie");
Map<String, List<String>> namesMap = new HashMap<String, List<String>>();
namesMap.put(johnny, johnnyNameList);
namesMap.put(katie, katieNameList);
...
List<String> recognitionResult = (ArrayList<String>) results.get(RESULTS_RECOGNITION);
for (String resultItem : recognitionResult) {
//brake into pieces the results
String[] messagePieces = resultItem.split(",");
//you process in case the length of the result fits
if(messagePieces.length == 4){
//compare predefined name collection with the result first element
//A) solution
for (String name : johnnyNameList) {
if(name.trim().toLowerCase().equals(messagePieces[0])){
//you have a name match
}
}
//B) solution process namesMap which contains all names
...
//you can compare the other parts of the result
//remove first element of the result
for (String piece : messagePieces) {
//count matches on the other words
}
}
}
I did something similar in my project, where i had commands and i had to recognize them and execute processes.
You can use https://github.com/Simmetrics/simmetrics
for example:
float allowD = 0.95f;
AbstractStringMetric metric = new JaroWinkler();
if (metric.getSimilarity(choice.toLowerCase(), fromTextRecognizer.trim().toLowerCase()) > allowD) {
// match found
}
This libs also provide other metrics that can be used
Related
I have to implement a filter + search functionality in an Android app (for a university course).
The app lists food companies and makes them searchable. The database we have to use is Firestore.
The filter + search mechanism I have to implement looks like this:
Get all documents which fulfill the filter settings.
Of those documents do an OR query over multiple fields to compare field values with strings of the search bar.
Unfortunately, this seems to be a really complex task in Firestore.
I am well aware of all the other questions asking only for parts of my problem (how to do logical OR queries, how to search over multiple fields etc.). But I struggle since two days to build a working implementation from those solutions.
The document for one company looks like this (simplified):
String name
String description
String[] types -> ["shop", "producer", "restaurant", ...]
Map[] openingHours -> Map[] Monday -> [begin, end]
-> Map[] Tuesday -> [begin, end]
...
Map[] productGroups -> String category
Boolean rawProduct
String[] seasons
String[] tags
...
-> String category
Boolean rawProduct
String[] seasons
String[] tags
...
The problems which I have to solve in combination are:
Problem 1: How to filter for productGroups->category, afterwards for rawProduct and after that for seasons for each product of each company?
Problem 2: How would an AND query for problem 1 look like, if array-contains can only be used once in a query? Creating new fields for all kinds of filter combinations and search them seems overkill (I have to filter for 20+ fields).
Problem 3: How to build from all those "problem-2"-queries logical OR queries, to compare string values in multiple fields like name, description, types[] and productGroups[]->tags[]?
Could someone give me a hint how to break down this problem into simpler queries without getting lost?
I have some troubles with a issue in my Android App. Hope someone can help me to solve this.
I have two lists. One list with Skills and one list with employees.
What I want is a list per Skill with all employees who have that skill.
I thought about this:
List SkillsWithEmployees
Skill 1 -> (Employee1, Employee2 and Employee3)
Skill 2 -> (Employee2 and Employee3)
Skill 3 -> (Employee1, Employee4 and Employee5)
Have someone an solution for me how I can do this? Or maybe other ideas to do something like this?
My result have to be that I can ask "I want all employees with Skill 2"
To expand on Kkba's answer, a HashMap is probably your best way of organising your data, if you are grouping subsections of employees by skill. As each skill is unique, it can be used as the key part of the HashMap like so:
HashMap<Skill, Employee> skillMap = new HashMap();
skillMap.put(firstSkill, Arrays.asList(employee1, employee3);
skillMap.put(secondSkill, Arrays.asList(employee2, employee3);
skillMap.put(thirdSkill, Arrays.asList(employee1, employee2, employee4);
And the list of employees using a certain skill can be accessed with:
skillMap.get(firstSkill); // Returns employee1 and employee3
But keep in mind that get() returns null if the key does not exist. You may want to use
skillmap.getOrDefault(emptySkill, Collections.emptyList());
instead to ensure a List is always returned regardless of if the skill exists.
Further reading: Arrays.asList(), HashMap.getOrDefault()
I would approach this in a couple ways. Using a Map<Skill, List<Employee>> is perfectly fine so long as you don't intend to modify your collection. If you do however, then it can quickly become a pain to add new keys and values.
With that in mind, if you want to have a mutable collection type, then I would use some form of MultiMap. The standard Java SDK doesn't include an implementation, but you can find one easily enough online (a proto-implementation is present in the Java Documentation), or supplied via a library (i.e. Guava's Multimap)
Alternatively, create a class that pairs Skills to Employees, and filter a collection of them based on a predicate. For example:
class SkilledEmployee {
private final Skill skill;
private final Employee employee;
SkilledEmployee(Skill skill, Employee employee) {
this.skill = skill;
this.employee = employee;
}
Skill skill() {
return skill;
}
Employee employee() {
return employee;
}
}
// To find employees by skill, using Java 8...
listOfSkilledEmployees.stream()
.filter(se -> se.skill().equals(SKILL_ONE)) //Filter out employees with Skill1
.map(SkilledEmployee::employee)
.forEach(employeeWithSkillOne -> { /*Do something */});
HashMap<String, ArrayList<String>>
"Skill1", ArrayList<"Employee1", "Employee2", "Employee3">
"Skill2", ArrayList<"Employee2", "Employee3">
"Skill3", ArrayList<"Employee1", "Employee4", "Employee5">
Android, Kotlin 1.2.
I have code like
data class Item(val id:Int,val field1:String, val field3:Array<String>,val field2:String)
val items:List<Item> = ....
var str:String='string_to_search'
I need to filter items list by str so I get sublist which contains onyly items in which str is case-insensitive substring of either field1 or field2 or both (it doesn't matter which one was matched or exact offset).
Right now I use code like this:
filteredItems=items
.filter { filtertFunc(it,filter) }
...
fun filtertFunc(item: Item, filter:String):Boolean {
if (item.field1.contains(filter, ignoreCase = true)) {
return true
}
if (item.field2.contains(filter, ignoreCase = true)) {
return true
}
return false
}
list of items usually contains 2-3k items. field1 and field2 are usually 30-300 usually. Search string is 0-50 chars.
Search string changes several times per second (usually new chars added - so abc changes to abcd ). List of items changes rarely.
My code have performance on some devices (filter took several seconds which is bad).
I can't use .parallelStream (I need to support Android 5.x but devices have usually at least 2 cores).
Using parallel map (from Parallel operations on Kotlin collections?) + special flag field in Item + filter does not help too much.
I thought about adding hash map with artificial keys (field1+field3) (or sorting list and using binarySearch) but this wont help because search string is not necessarily occurs at start of field1/field3.
How to better solve this performance issue? Any (sane) amount of pre-processing on list is ok.
Search string changes several times per second (usually new chars
added - so abc changes to abcd ). List of items changes rarely.
You may filter the result of previous filtration after the search string growing.
If search string reduced you may return to previous result.
I have an application where I need to return the first user found that meets certain criteria, some of that criteria is having a certain number of objects stored.
For example, let's say I want to return the first store I can find that has at-least 3 employees with atleast two children. I know, what an odd-ball example. So I would have a query something like this:
PFUser.query()?
.whereKey("objectId", notEqualTo: PFUser.currentUser()?.objectId!)
.includeKey("stores.employees.children")
// .whereCountForkey("stores.employees", greaterThan: 2)
// .whereCountForKey("stores.employees.children", greaterThan: 1)
.getFirstObject();
Notice the commented out lines, I'm trying to find a way to do soemthing like this in a single query. I'm using parse, which I believe uses MongoDB on the back end, but I don't believe you can execute custom database queries..?
This is a mobile application for both iOS and Android, although the code shown is in SWIFT I have two variations of the project. Examples in either swift, obj-C, Java, or C# will be fine.
Also more than happy with Cloud-code solutions.
There is an example in the documentation
var Team = Parse.Object.extend("Team");
var teamQuery = new Parse.Query(Team);
teamQuery.greaterThan("winPct", 0.5);
var userQuery = new Parse.Query(Parse.User);
userQuery.matchesKeyInQuery("hometown", "city", teamQuery);
userQuery.find({
success: function(results) {
// results has the list of users with a hometown team with a winning record
}
});
I'm creating an android app which has selection of company and based on that I show cars and based on selection of particular car, I want to show some details of car e.g. capacity, power, engine oil etc. Now I'm using array to store all this car related information. e.g.
private static final String[] car1={"624CC","33bhp","10W40"}
private static final String[] car2={"1600CC","120bhp","10W40"}
To check the section, I've used multiple if-else statements for each car. And depending on the selection, I show value form array.
if(bn.equals("car 1"))
{
cap.setText(""+car1[0]);
powr.setText(""+car1[1]);
oil.setText(" "+car1[2]);
}
else if(bn.equals("car 2"))
{
cap.setText(""+car2[0]);
powr.setText(""+car2[1]);
oil.setText(" "+car2[2]);
}
else if(bn.equals("car 3"))
{
cap.setText(""+car3[0]);
powr.setText(""+car3[1]);
oil.setText(" "+car3[2]);
}
Now the problem is as the number of if-else have increased,I'm getting error of "Code too large" in android studio.
I was wondering if is there any way to replace these multiple if else statements with single, generalised statement. As you can see, in all if else, the code is the same, its just that array name is different.
I'm aware that I can use SQLite db, but I'll have to add all the values to it for all the cars again. So was wondering if I can use the same array that I've created. Any solution/suggestion will be really helpful
Probably in place of string comparison of names you can store the index of the value selected and use switch case to find out which car is selected. This should reduce the code also make it much more readable.