How to retrieve a string array from a cursor - java

I have a cursor, called passableCursor, containing multiple fields, However one field,ingredients, holds multiple values and I'm unable to get all the values from it.
Example of retrieving from name
Log.d("recipeName", passableCursor.getString(passableCursor.getColumnIndex("name")));
Example of cursor structure
name-> name1
description -> description1
ingredients -> ingredient1, ingredient2, ingredient3.
I've been using getString for the name and description field. However, I'm struggling to get the values from ingredients. There doesn't seem to get a getStringArray method.

Here is one way:
SQLiteDatabase db =null;//Initialize this first
Cursor cursor = db.rawQuery("your query", null);//Replace with your query(e.g. SELECT FROM table WHERE something=2)
String preChanged = cursor.getString(cursor.getColumnIndex("row_name"));//Replace row name with your row name
String[] finalR = preChanged.split(",");//Can be changed to parts
//String[] finalR = new String[parts.length];
//for(int i = 0; i < parts.length; i++){
// finalR[i] = parts[i];//This for-loop is if you have special needs. If you want to convert the String to a different type(integer, boolean, etc), or you want to make sure it contains/does not contain something.
//}//Uncomment if needed
//Now, this needs a special compression method, to ensure correct format;
//raw is the raw array, continuing from up above we use finalR to make sure you as a reader understand the context
StringBuilder builder = new StringBuilder();
for (int i = 0; i < finalR.length; i++) {
if(i != finalR.length - 1)
builder.append(finalR[i] + ",");
else
builder.append(finalR[i]);
}
This can be converted into a series of methods as well.
Explanation of how this works:
1) Take raw array input(String in this case)
2) Create a single String, separating the different Strings with a ,. For longer Strings where there may be a comma, you may want to consider adding a backslash to the comma, and split at "\,"(two backslashes to make Java register it as an actual backslash, and not an escape char)
3) Save the String to your database
4) Load the String
5) It splits the string at ,, giving you several pieces. This is the array, and should be(assuming you have taken precautions protecting the system from in-string commas(,)
6) OPTIONAL: Refine the String array, by removing something, adding something, adding support for markup(replace [link text](http://example.com) with HTML code), change the type(string -> integer), whatever you need.
NOTE
This is the basic draft. This allows you to save basic arrays to a database, and recover it without having to create multiple rows. It may need refining, if you save in the String array text with commas, or any char that may attempt to cause SQL injection.
This can be refined to work with any other types of arrays, for an instance long, integer or boolean, but the saving is the same(it has to be compressed to a string), but you add .parse[Type](input) to convert it to an array of the desired type

Related

Java - How to display all substrings in String without using an array

I have a string which is :
1|name|lastname|email|tel \n
2|name|lastname|email|tel \n
I know that I have to use a loop to display all lines but the problem is that in my assignment
I can't use arrays or other classes than String and System.
Also I would like to sort names by ascending order without using sort method or arrays.
Do I have to use compareTo method to compare two names ?
If that's the case, how do I use compareTo method to sort names.
For example, if compareTo returns 1, that means that the name is greater than the other one. In that case how do I manage the return to sort name properly in the string ?
To display all substrings of the string as in the example, you can just go through all characters one by one and store them in a string. Whenever you hit a delimiter (e.g. | or \n), print the last string.
Here's a thread on iterating through characters of a string in Java:
What is the easiest/best/most correct way to iterate through the characters of a string in Java?
If you also need to sort the names in ascending order without an array, you will need to scan the input many times - sorting N strings takes at least N*log(N) steps. If this is a data structure question, PriorityQueue should do the trick for you - insert all substrings and then pop them out in a sorted fashion :)
building on the previous answer by StoneyKeys, since i do not have the privilege to comment, you can use a simple if statement that when the char is a delimiter, System.out.println() your previous scanned string. Then you can reset the string to an empty string in preparation for scanning the next string.
In java, there are special .equals() operators for strings and chars so when you won't be using == to check strings or char. Do look into that. To reset the value of string just assign it a new value. This is because the original variable points at a certain string ie "YHStan", by making it point at "", we are effectively "resetting" the string. ie scannedstr = "";
Please read the code and understand what each line of code does. The sample code and comments is only for your understanding, not a complete solution.
String str ="";
String value = "YH\nStan";
for (int i=0; i <value.length(); i++) {
char c = value.charAt(i);
String strc = Character.toString(c);
//check if its a delimiter, using a string or char .equals(), if it is print it out and reset the string
if (strc.equals("\n")) {
System.out.println(str);
str ="";
continue; // go to next iteration (you can instead use a else if to replace this)
}
//if its not delimiter append to str
str = str +strc;
//this is to show you how the str is changing as we go through the loop.
System.out.println(str);
}
System.out.println(str); //print out final string result
This gives a result of:
Y
YH
YH
S
St
Sta
Stan
Stan

Extracting Substrings from a List in Java

If I have a parent string (let's call it output) that contains a list of variable assignments like so ...
status.availability-state available
status.enabled-state enabled
status.status-reason The pool is available
And I want to extract the values of each variable in that list given the variable names, ie the substring after the space following status.availability-state, status.enabled-state, and status.status-reason, such that I end up with three different variable assignments making each of the following String comparisons true ...
String availability = output.substring(TODO);
String enabled = output.substring(TODO);
String reason = output.substring(TODO);
availability.equals("available");
enabled.equals("enabled");
reason.equals("The pool is available");
What is the simplest way to do this? Should I even use substring for this?
This is a little tricky because you need to assign the value to a specific variable - you can't just have a map of keys to variables in Java.
I would consider doing this with a switch:
for (String line : output.split('\n')) {
String[] frags = line.split(' ', 2); // Split the line in 2 at the space.
switch (frags[0]) { // This is the "key" of the variable.
case "status.availability-state":
availability = frags[1]; // This assigns the "value" to the relevant variable.
break;
case "status.enabled-state":
enabled = frags[1];
break;
// ... etc
}
}
It's not very pretty, but you don't have too many options.
There seem to be two questions here -- how to parse the string, and how to assign to variables by name.
Tackle the string parsing one step at a time:
first write a program to read one line at a time and output each one in the body of a loop. String.split() or StringTokenizer are two options here.
next enhance this by writing a method to handle one line. The same tools are helpful here, to split on spaces.
You should now have a program that can print name: status.availability-state, value: available for each line of input.
Next, you're asking to programatically assign to variables based on the name of the parameter.
There is no legitimate way to look at a variable's name at runtime (OK, Java 8 reflection has ways, but it shouldn't be used without very good reason).
So, the best you can do is to use a switch or if statement:
switch(name) {
case status.availability-state:
availability = value;
break;
... etc.
}
However, whenever you use switch or if you should think about whether there's a better way.
Is there any reason you can't turn these variables into Map entries?
configMap.add(name,value);
Then to read it:
doSomethingWith(configMap.get("status.availability");
That's what maps are for. Use them.
This is a similar situation to the rookie mistake of using variables called person1, person2, person3... instead of using an array. Eventually they ask "How do I go from the number 25 to my variable person25?" -- and the answer is, you can't, but an array or list makes it easy. people[number] or people.get(number)
A valid alternative is to split the string by \n and add to a Map. Example:
String properties = "status.availability-state available\nstatus.enabled-state enabled\nstatus.status-reason The pool is available";
Map<String, String> map = Arrays.stream(properties.split("\n"))
.collect(Collectors.toMap(s -> s.split(" ")[0], s -> s.split(" ", 2)[1]));
System.out.println(map.get("status.status-reason"));
Should output The pool is available
This loop will match and extract the variables, and you can then assign them as you see fit:
Pattern regex = Pattern.compile("status\\.(.*?)-.*? ([a-z]+)");
Matcher matcher = regex.matcher(output);
while (matcher.find()) {
System.out.println(matcher.group(1) + "=" + matcher.group(2));
}
status\\. matches "status."
(.*?) matches any sequence of characters but isn't greedy, and captures them
-.* matches dash, any chars, space
([a-z]+) matches any string of lower-case letters, and captures them
Here's one way to do it:
Map<String, String> properties = getProperties(propertiesString);
availability = properties.get("availability-state");
enabled = properties.get("enabled-state");
reason = properties.get("status-reason");
// ...
public void getProperties(String input) {
Map<String, String> properties = new HashMap<>();
String[] lines = output.split("\n");
for (String line : lines) {
String[] parts = line.split(" ");
int keyStartIndex = parts[0].indexOf(".") + 1;
int spaceIndex = parts[1].indexOf(" ");
string key = parts[0].substring(keyStartIndex, spaceIndex);
properties.put(key, parts[1]);
}
return properties;
}
This seems to be a bit more straight-forward, in terms of the code that's setting these values, as each value is set to exactly the value from the map, rather than iterating over some list of strings and seeing if it contains a particular value and doing different things based on that.
This is designed with the primary use-case being that the string is created at runtime in memory. If the properties are created in an external file, this code would still work (after creating the desired String in memory), but it may be a better idea to use either a Properties file, or perhaps a Scanner.

parsing values from text file in java

I've got some text files I need to extract data from. The file itself contains around a hundred lines and the interesting part for me is:
AA====== test==== ====================================================/
AA normal low max max2 max3 /
AD .45000E+01 .22490E+01 .77550E+01 .90000E+01 .47330E+00 /
Say I need to extract the double values under "normal", "low" and "max". Is there any efficient and not-too-error-prone solution other than regexing the hell out of the text file?
If you really want to avoid regexes, and assuming you'll always have this same basic format, you could do something like:
HashMap<String, Double> map = new HashMap<>();
Scanner scan = new Scanner(filePath); //or your preferred input mechanism
assert (scan.nextLine().startsWith("AA====:); //remove the top line, ensure it is the top line
while (scan.hasNextLine()){
String[] headings = scan.nextLine().split("\\s+"); //("\t") can be used if you're sure the delimiters will always be tabs
String[] vals = scan.nextLine().split("\\s+");
assert headings[0].equals("AA"); //ensure
assert vals[0].equals("AD");
for (int i = 1; i< headings.length; i++){ //start with 1
map.put(headings[i], Double.parseDouble(vals[i]);
}
}
//to make sure a certain value is contained in the map:
assert map.containsKey("normal");
//use it:
double normalValue = map.get("normal");
}
Code is untested as I don't have access to an IDE at the moment. Also, I obviously don't know what's variable and what will remain constant here (read: the "AD", "AA", etc.), but hopefully you get the gist and can modify as needed.
If each line will always have this exact form you can use String.split()
String line; // Fill with one line from the file
String[] cols = line.split(".")
String normal = "."+cols[0]
String low = "."+cols[1]
String max = "."+cols[2]
If you know what index each value will start, you can just do substrings of the row. (The split method technically does a regex).
i.e.
String normal = line.substring(x, y).trim();
String low = line.substring(z, w).trim();
etc.

How to design String decollator in a string contains many params

I need pass a string parameter that contains many params. When receive the parameter, I use String.split() to split it to get all the params.
But one promblem accured. How to design my string decollator so that any ASCII CODE on keyboard can be passed correctly.
Hope for any advice.
Maybe you could have a look at variadic arguments instead of splitting a string. For example:
public void method(String... strings) {
// strings is actually an array
String firstParam = strings[0];
String secondParam = strings[1];
// ...
}
Calling:
method("string1");
method("string1", "string2", "string3");
// as many string args as you want
If I understood correctly - you need to encode set of parameters to one string. You can use some sequence of characters for this purpose, E.g.
final String delimiter = "###"
String value = "param1###param2###param3";
String[] parameters = value.split(delimiter);
Choose a character which is easy to enter and unlikely to appear in the input. Let's assume that character is #.
Normal input would like like Item 1#Item 2#Item 3. Actually, you can .trim() every item and let the user enter Item 1 # Item 2 # Item 3 if s/he prefers.
However, like you describe, say the user would like to enter Item #1, Item #2, etc.. There are a few ways to let him/her do this, but the easier is to let them escape the delimiter. For example, instead of Item #1 # Item #2 # Item #3, which would result in 6 different items being found normally, let the user enter, for example Item ##1 # Item ##2 # Item ##3. Then in your parsing, make sure to handle the case when two or more #'s have been entered in a row. split likely won't be good enough, you'll have to go through the string yourself.
Here's a sketch of a method which would split the input string for you:
private static List<String> parseArguments(String input) {
ArrayList<String> arguments = new ArrayList<String>();
String[] prelArguments = input.split("#");
for (int i = 0; i < prelArguments.length; i++) {
String argument = prelArguments[i];
if (argument.equals("")) {
// We will enter here if there were two or more #'s in a row
StringBuilder combinedArgument = new StringBuilder(arguments.remove(arguments.size() - 1));
int inARow = 0;
while (prelArguments[i+inARow].equals("")) {
inARow++;
combinedArgument.append('#');
}
i += inARow;
combinedArgument.append(prelArguments[i]);
arguments.add(combinedArgument.toString());
} else {
arguments.add(argument);
}
}
return arguments;
}
Error handling, edge-case handling and some performance improvement is missing from the above, but I think the idea comes through.
I would eliminate the problem, which is the misuse of String as an argument container. If you need to pass more parameters, pass more parameters. If this gets out of hand, consider passing a map, or a custom object that can contain all the parameters.

two dimensional array in java - difficulties

I'm used to python and django but I've recently started learning java. Since I don't have much time because of work I missed a lot of classes and I'm a bit confused now that I have to do a work.
EDIT
The program is suppose to attribute points according to the time each athlete made in bike and race. I have 4 extra tables for male and female with points and times.
I have to compare then and find the corresponding points for each time (linear interpolation).
So this was my idea to read the file, and use an arrayList
One of the things I'm having difficulties is creating a two dimensional array.
I have a file similar to this one:
12 M 23:56 62:50
36 F 59:30 20:60
Where the first number is an athlete, the second the gender and next time of different races (which needs to be converted into seconds).
Since I can't make an array mixed (int and char), I have to convert the gender to 0 and 1.
so where is what I've done so far:
public static void main(String[] args) throws FileNotFoundException {
Scanner fileTime = new Scanner (new FileReader ("time.txt"));
while (fileTime.hasNext()) {
String value = fileTime.next();
// Modify gender by o and 1, this way I'm able to convert string into integer
if (value.equals("F"))
value = "0";
else if (value.equals("M"))
value = "1";
// Verify which values has :
int index = valor.indexOf(":");
if (index != -1) {
String [] temp = value.split(":");
for (int i=0; i<temp.length; i++) {
// convert string to int
int num = Integer.parseInt(temp[i]);
// I wanted to multiply the first number by 60 to convert into seconds and add the second number to the first
num * 60; // but this way I multiplying everything
}
}
}
I'm aware that there's probably easier ways to do this but honestly I'm a bit confused, any lights are welcome.
Just because an array works well to store the data in one language does not mean it is the best way to store the data in another language.
Instead of trying to make a two dimensional array, you can make a single array (or collection) of a custom class.
public class Athlete {
private int _id;
private boolean _isMale;
private int[] _times;
//...
}
How you intend to use the data may change the way you structure the class. But this is a simple direct representation of the data line you described.
Python is a dynamically-typed language, which means you can think of each row as a tuple, or even as a list/array if you like. The Java idiom is to be stricter in typing. So, rather than having a list of list of elements, your Java program should define a class that represents a the information in each line, and then instantiate and populate objects of that class. In other words, if you want to program in idiomatic Java, this is not a two-dimensional array problem; it's a List<MyClass> problem.
Try reading the file line by line:
while (fileTime.hasNext())
Instead of hasNext use hasNextLine.
Read the next line instead of next token:
String value = fileTime.next();
// can be
String line = fileTime.nextLine();
Split the line into four parts with something as follows:
String[] parts = line.split("\\s+");
Access the parts using parts[0], parts[1], parts[2] and parts[3]. And you already know what's in what. Easily process them.

Categories