I am currently trying to parse a .txt file (subtitles file) to a .csv table.
Example out of the file:
22
00:03:36,717 --> 00:03:38,344
(thunder crashing)
I figured using the StringList Type was my best choice for that and I almost got all my information ready. The only thing left is, that I want the second line with the start pos. and the end pos. to be in seperate strings, following each other, like this:
22
00:03:36,717
00:03:38,344
(thunder crashing)
I already know how to do it with the substring() method, but I can't figure out how to add the new String at a specific index. the set function overwrites it and the appends function can only add it to the end of the list.
Is the use of an ArrayList better in hindsight? I tried doing that, but then I couldn't figure out how to use the actual element. What I have is this:
String s[] = loadStrings("subtest.txt");
ArrayList lines= new ArrayList();
for (int i=0; i<s.length; i++){
lines.add(s[i]);
}
which added all the lines in seperate elements of the ArrayList. Now I can't access the element as a string however. If I want to get the length of a specific element, it tells me that the length() function doesn't exist and I can't save the element as a string either.
Thanks for looking into it!
The problem is that, by default, ArrayList contains a list of Objects rather than a list of Strings, so the objects you get out of it will be of the wrong data type. Because the result of ArrayList.get() is an Object, you can't assign it to a String or call methods of the String class on it (such String.length()).
What you want are type generics. Because ArrayList is a generic class, you can use the generics syntax to specify the type of objects it should hold:
ArrayList<String> lines = new ArrayList<String>(); //creates a list of Strings
Processing provides a more complete example in their documentation of the ArrayList class.
Considering the XY problem, you probably need to replace " --> " with a new line, like this:
MainP:
public static void main ( String [ ] args ) throws IOException
{
Path path = Paths.get("yourFilePath.txt");
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);
content = content.replaceAll(" --> ", "\n");
Files.write(path, content.getBytes(charset));
}
Input:
1
00:00:00,000 --> 00:00:01,567
Anteriormente en Vikings...
2
00:00:01,765 --> 00:00:03,298
Voy a ir de nuevo a saquear Inglaterra,
3
00:00:03,300 --> 00:00:05,233
para la venganza de la
destrucción del asentamiento.
Output:
1
00:00:00,000
00:00:01,567
Anteriormente en Vikings...
2
00:00:01,765
00:00:03,298
Voy a ir de nuevo a saquear Inglaterra,
3
00:00:03,300
00:00:05,233
para la venganza de la
destrucción del asentamiento.
Note: This way you are overwriting the input file.
Related
So I'm trying retrieve specific substrings in values in a Hashmap constructed like this..
HashMap<ID, "Home > Recipe > Main Dish > Chicken > Chicken Breasts">
Which is passed from a different method that returns a HashMap
In above example, I need to retrieve Chicken.
Thus far, I have..
public static ArrayList<String> generalize() {
HashMap<String, String> items = new HashMap<>();
ArrayList<String> cats = new ArrayList<>();
items = RecSys.readInItemProfile("PATH", 0, 1);
for(String w : items.values()) {
cats.add(w);
}
for(String w : cats) {
int e = w.indexOf('>', 1 + w.indexOf('>', 1 + w.indexOf('>')));
String k = w.substring(e+1);
System.out.print(k);
e = 0;
}
System.out.println("k" + cats);
return cats;
}
Where I try to nullify String e for each iteration (I know it's redundant but it was just to test).
In my dataset, the first k-v pair is
3880=Home > Recipes > Main Dish > Pasta,
My output is
Pasta
Which is ok. If there are more than 3x ">", it'll return all following categories. Optimally it wouldn't do that, but it's ok if it does. However, further down the line, it (seemingly) randomly returns
Home > Recipe
Along with the rest of the data...
This happens at the 6th loop, I believe.
Any help is greatly appreciated..
Edit:
To clarify, I have a .csv file containing 3 columns, whereas 2 are used in this function (ID and Category). These are passed to this function by a read method in another class.
What I need to do is extract a generalized description of each category, which in all cases is the third instance of category specification (that is, always between the third and fourth ">" in every k-v pair).
My idea was to simply put all values in an arraylist, and for every value extract a string from between the third and fourth ">".
I recommend using the following map:
Map<Integer, List> map = new HashMap<>();
String[] vals = new String[] { "HomeRecipe", "Main Dish", "Chicken",
"Chicken Breasts" };
map.put(1, Arrays.asList(vals));
Then, if you need to find a given value in your original string using an ID, you can simply call ArrayList#get() at a certain position. If you don't care at all about order, then a map of integers to sets might make more sense here.
If you can. change your data structure to a HashMap<Integer, List<String>> or HashMap<Integer, String[]>. It's better to store the categories (by cats you mean categories right?) in a collection instead of a string.
Then you can easily get the third item.
If this is not possible. You need to do some debugging. Start by printing every input and output pair and find out which input caused the unexpected output. Your indexOf method seems to work at first glance.
Alternatively, try this regex method:
String k = cats.replaceAll("(?:[^>]+\\s*>\\s*){3}([^>]+).*", "$1");
System.out.println(k);
The regex basically looks for a xxx > yyy > zzz > aaa ... pattern and replaces that pattern with aaa (whatever that is in the original string).
I have this array:
String[] countriesList = {
"Japan",
"Sverige",
"Tyskland",
"Spanien",
"Syrien",
"Litauen",
};
I want to be able to add another thing to the array, in this case this [6]th position. Is it possible to do this by JOPtionPane? This is what I've done this far, however nothing happens nor does any errors occur.
String addland = JOptionPane.showInputDialog("Vilket land vill du lägga till?").trim();
countriesList[6] = addland;
Arrays start their counting from 0, so you could use countriesList[5] = addland;
You may use a dynamic list to perform your task.
They are better in every situation and should be superior to simple Arrays
Try to use this
List<String> countriesList = new ArrayList<>(
Arrays.asList("Japan", "Sverige", "Tyskland", "Spanien", "Syrien", "Litauen"));
String addland = JOptionPane.showInputDialog("Vilket land vill du lägga till?").trim();
countriesList.set(5,addland);
System.out.println(countriesList);
Output, after entering asdadsad:
[Japan, Sverige, Tyskland, Spanien, Syrien, asdadsad]
To add a land to the existing list use countriesList.add(addland); instead of countriesList.set(5,addland);
I am trying to get some values from config file. I have lot of keys and want to get only certain values. These values have keys starting with same initial name with a slight variation towards the end.
can Someone help me quickly?
assuming when you say key you mean value (as in values in an array),
final String PREFIX = "yourPrefix";
for(String value : valueList) {
if(value.startwith(PREFIX)) {
<do whatever...>
}
here is the link to the java Doc
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#startsWith(java.lang.String)
I am assuming you are scanning the config file for Strings that have similar prefixes. Why not try scanning them in grouped instead of scanning them in all in one hashmap. If you know already the specified prefixes try creating an arraylist for each prefix and while scanning receive the given prefix and add it accordingly.
StringTokenizer s = new StringTokenizer ("Configuration File : Server_intenties = keyId_11503, keyId_11903 : Server_passcodes = keyCode_1678, keyCode_9893", " ");
ArrayList<String> keyCode = new ArrayList();
ArrayList<String> keyId = new ArrayList();
while(s.hasMoreTokens){
String key = s.nextToken
if(key.contains("keyId")){
keyId.add(key);
}
if(key.contains("keyCode")){
keyCode.add(key);
}
}
System.out.println(keyCode);
System.out.println(keyId);
I got a problem regarding parsing XML data. I have divided my program into 3 different java files, each containing a class. One of them is rssparser.java. This file holds a function called iterateRSSFeed(String URL), this function returns a string containing the parsed description tag. In my main.java files where my main method is, I call this iterateRSSFeed function this way:
rssparser r = new rssparser();
String description = r.iterateRSSFeed();
And then I am planning to add this String to a JLabel, this way:
JLabel news = new JLabel(description);
which obviously works great, my program runs. BUT there are more description tags in my XML file, the JLabel only contains one(1) parsed description tag. I should say that my return statement in the iterateRSSFeed function is "packed" in a for-loop, which in my head should return all of the description tags. But no.
Please ask if something is uncleared or showing of the source code is a better way to provide a solution to my answer. Thanks in advance! :)
When Java executes a return statement, it will leave the method, and not continue running the loop.
If you want to return multiple values from a method, you have to put them in some object grouping them together. Normally one would use a List<String> as return type.
Then your loop will fill the list, and the return statement (after the loop) can return the whole list at once.
If you want to have one large string instead of multiple ones, you'll have to merge them into one.
The easiest would be to simply use the .toString() method on the list, this will give (if you are using the default list implementations) something like [element1, element2, element3].
If you don't like the [,], you could simply concatenate them:
List<String> list = r.iterateRSSFeed();
StringBuilder b = new StringBuilder();
for(String s : list) {
b.append(s);
}
String description = b.toString();
This will give element1element2element3.
As Java's JLabel has some rudimentary HTML support, you could also use this to format your list as a list:
List<String> list = r.iterateRSSFeed();
StringBuilder b = new StringBuilder();
b.append("<html><ul>");
for(String s : list) {
b.append("<li>");
b.append(s);
b.append("</li>");
}
b.append("</ul>");
String description = b.toString();
The result will be <html><ul><li>element1</li><li>element2</li><li>element3</li></ul>, which will be formatted by the JLabel as something like this:
element1
element2
element3
I need to convert a String representation of a nested List back to a nested List (of Strings) in Groovy / Java, e.g.
String myString = "[[one, two], [three, four]]"
List myList = isThereAnyMethodForThis(myString)
I know that there's the Groovy .split method for splitting Strings by comma for example and that I could use regular expressions to identify nested Lists between [ and ], but I just want to know if there's an existing method that can do this or if I have to write this code myself.
I guess the easiest thing would be a List constructor that takes the String representation as an argument, but I haven't found anything like this.
In Groovy, if your strings are delimited as such, you can do this:
String myString = "[['one', 'two'], ['three', 'four']]"
List myList = Eval.me(myString)
However, if they are not delimited like in your example, I think you need to start playing with the shell and a custom binding...
class StringToList extends Binding {
def getVariable( String name ) {
name
}
def toList( String list ) {
new GroovyShell( this ).evaluate( list )
}
}
String myString = "[[one, two], [three, four]]"
List myList = new StringToList().toList( myString )
Edit to explain things
The Binding in Groovy "Represents the variable bindings of a script which can be altered from outside the script object or created outside of a script and passed into it."
So here, we create a custom binding which returns the name of the variable when a variable is requested (think of it as setting the default value of any variable to the name of that variable).
We set this as being the Binding that the GroovyShell will use for evaluating variables, and then run the String representing our list through the Shell.
Each time the Shell encounters one, two, etc., it assumes it is a variable name, and goes looking for the value of that variable in the Binding. The binding simply returns the name of the variable, and that gets put into our list
Another edit... I found a shorter way
You can use Maps as Binding objects in Groovy, and you can use a withDefault closure to Maps so that when a key is missing, the result of this closure is returned as a default value for that key. An example can be found here
This means, we can cut the code down to:
String myString = "[[one, two], [three, four]]"
Map bindingMap = [:].withDefault { it }
List myList = new GroovyShell( bindingMap as Binding ).evaluate( myString )
As you can see, the Map (thanks to withDefault) returns the key that was passed to it if it is missing from the Map.
I would parse this String manually. Each time you see a '[' create a new List, each time you see a ',' add an element to the list and each time you see a ']' return.
With a recursive method.
public int parseListString(String listString, int currentOffset, List list){
while(currentOffset < listString.length()){
if(listString.startsWith("[", currentOffset)){
//If there is a [ we need a new List
List newList = new ArrayList();
currentOffset = parseListString(listString, currentOffset+1, newList);
list.add(newList);
}else if(listString.startsWith("]", currentOffset){
//If it's a ], then the list is ended
return currentOffset+1;
}else{
//Here we have a string, parse it until next ',' or ']'
int nextOffset = Math.min(listString.indexOf(',', currentOffset), listString.indexOf(']', currentOffset));
String theString = listString.substring(int currentOffset, int nextOffset);
list.add(theString);
//increment currentOffset
currentOffset = nextOffset;
}
}
return currentOffset;
}