So I'm trying to manipulate the user's input in such a way that when I find a certain string in his input I turn that into a variable and replace the string with the name of the variable. (jumbled explanation I know, maybe an example will make it more clear).
public class Test {
static List<String> refMap = new ArrayList<String>();
public static void main(String[] args) {
String x = "PROPERTY_X";
String y = "PROPERTY_Y";
refMap.add(x);
refMap.add(y);
String z = "getInteger("PROPERTY_X)";
String text = "q=PROPERTY_X+10/(200*PROPERTY_X)";
String text1 = "if(PROPERTY_X==10){"
+ "j=1;"
+ "PROPERTY_X=5; "
+ "if(true){"
+ "m=4/PROPERTY_X"
+ "}"
+ "}";
detectEquals(text);
}
public static String detectEquals(String text) {
String a = null;
text = TestSplitting.addDelimiters(text);
String[] newString = text.split(" ");
List<String> test = Arrays.asList(newString);
StringBuilder strBuilder = new StringBuilder();
HashMap<String, Integer> signs = new HashMap<String, Integer>();
HashMap<String, Integer> references = new HashMap<String, Integer>();
List<String> referencesList = new ArrayList<String>();
List<Integer> indexList = new ArrayList<Integer>();
int index = 0;
for (int i = 0; i < test.size(); i++) {
a = test.get(i).trim();
//System.out.println("a= " + a);
strBuilder.append(a);
index = strBuilder.length() - a.length();
if (a.equals("=")) {
signs.put(a, index);
indexList.add(index);
// System.out.println("signs map--> : "+signs.get(a));
}
if (refMap .contains(a)) {
references.put(a, index);
// System.out.println("reference index-> "+references.get(a));
// System.out.println("reference-> "+references.toString());
}
}
//stuck here
for (String s : references.keySet()) {
//System.out.println("references-> " + s);
int position = references.get(s);
for (int j : indexList) {
if (j <= position) {
System.out.println(j);
}
}
//strBuilder.insert(j - 1, "temp1=\r\n");
}
System.out.println(strBuilder);
return a;
}
Say the user inputs the content of the string "text", I'm trying to parse that input so when I find "PROPERTY_X", I want to create a variable out of it and place it right before the occurrence of text, and then replace "PROPERTY_X" with the name of the newly created variable.
The reason I'm also searching for "=" sign is because I only want to do the above for the first occurrence of "PROPERTY_X" in the whole input and then just replace "PROPERTY_X" with tempVar1 wherever else I find "PROPERTY_X".
ex:
tempVar1=PROPERTY_X;
q=tempVar1+10/(200*tempVar1);
Things get more complex as the user input gets more complex, but for the moment I'm only trying to do it right for the first input example I created and then take it from there :).
As you can see, I'm a bit stuck on the logic part, the way I went with it was this:
I find all the "=" signs in the string (when I move on to more complex inputs I will need to search for conditions like if,for,else,while also) and save each of them and their index to a map, then I do the same for the occurrences of "PROPERTY_X" and their indexes. Then I try to find the index of "=" which is closest to the index of the "PROPERTY_X" and and insert my new variable there, after which I go on to replace what I need with the name of the variable.
Oh the addDelimiters() method does a split based on some certain delimiters, basically the "text" string once inserted in the list will look something like this:
q
=
PROPERTY_X
+
10
etc..
Any suggestions are welcome.
Related
Edit: As some have asked, I will try to make it more clear. The user inserts a value, any value, into a text box. This is saved as the result int. The problem is finding the right line to insert the strings to for every choice the user might make.
I am trying to insert strings through a loop in a file and as it is right now, I'm using a static declaration of the location (line number) through an int. The problem is that if the number of iterations changes, the strings are not inserted in the right location.
In the code below, result represents the number of strings to be inserted, as written by the user in a text box.
for (int a = result; a >= 1; a--) {
Path path = Paths.get("ScalabilityModel.bbt");
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
int position = 7;
String extraLine = "AttackNode" + a;
lines.add(position, extraLine);
Files.write(path, lines, StandardCharsets.UTF_8);
}
I would like to change "int position = 7" to something like position = "begin attack nodes" + 1 (so that the string is inserted on the line below the line that contains the string I'm looking for.
What's the easiest way to do this?
Assuming from the comments in the question that user wants to add 2 lines (for example). If user adds '2' into input box.
Please mention in the comment if I am missing something.
One of the way to get that can be:
public static void main(String[] args) throws IOException {
// Assuming the user input here
int result = 2;
for (int a = result; a >= 1; a--) {
Path path = Paths.get("ScalabilityModel.bbt");
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// Used CopyOnWriteArrayList to avoid ConcurrentModificationException
CopyOnWriteArrayList<String> myList = new CopyOnWriteArrayList<String>(lines);
// taking index to get the position of line when it matches the string
int index = 0;
for (String string : myList) {
index = index + 1;
if (string.equalsIgnoreCase("AttackNode")) {
myList.add(index, "AttackNode" + a);
}
}
Files.write(path, myList, StandardCharsets.UTF_8);
}
}
I moved the reading of the file to outside the loop and created a list of the lines to add. Since I wasn't sure what string you want to match with I added a variable searchString for this, so just replace it or assign the right value to it.
Path path = Paths.get("ScalabilityModel.bbt");
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
String searchString = "abc";
List<String> newLines = new ArrayList<>();
for (int i = 0; i < result; i++) {
String extraLine = "AttackNode" + (result - i);
newLines.add(extraLine);
}
for (int i = 0; i < lines.size(); i++) {
if (lines.get(i).contains(searchString)) { //Check here can be modified to equeals, startsWith etc depending on the search pattern
if (i + 1 < lines.size()) {
lines.addAll(i + 1, newLines);
} else {
lines.addAll(newLines);
}
break;
}
}
I have a method that takes in an ArrayList of strings with each element in the list equaling to a variation of:
>AX018718 Equine influenza virus H3N8 // 4 (HA)
CAAAAGCAGGGTGACAAAAACATGATGGATTCCAACACTGTGTCAAGCTTTCAGGTAGACTGTTTTCTTT
GGCATGTCCGCAAACGATTTGCAGACCAAGAACTGGGTGATGCCCCATTCCTTGACCGGCTTCGCCGAGA
This method is broken down into the Acc, which is AX018718 in this case and seq which are the two lines following the Acc
This is then checked by another ArrayList of strings called pal to see if the substrings match [AAAATTTT, AAACGTTT, AAATATATTT]
I am able to get all of the matches for the different elements of the first list outputted as:
AATATATT in organism: AX225014 Was found in position: 15 and at 15
AATATT in organism: AX225014 Was found in position: 1432 and at 1432
AATATT in organism: AX225016 Was found in position: 1404 and at 1404
AATT in organism: AX225016 Was found in position: 169 and at 2205
Is it possible to check if for all of the outputted information if all of the Acc match one pal?
In the case above, the wanted output would be:
AATATT was found in all of the Acc.
my working code:
public static ArrayList<String> PB2Scan(ArrayList<String> Pal) throws FileNotFoundException, IOException
{
ArrayList<String> PalindromesSpotted = new ArrayList<String>();
File file = new File("IAV_PB2_32640.txt");
Scanner sc = new Scanner(file);
sc.useDelimiter(">");
//initializes the ArrayList
ArrayList<String> Gene1 = new ArrayList<String>();
//initializes the writer
FileWriter fileWriter = new FileWriter("PB2out");
PrintWriter printwriter = new PrintWriter(fileWriter);
//Loads the Array List
while(sc.hasNext()) Gene1.add(sc.next());
for(int i = 0; i < Gene1.size(); i++)
{
//Acc breaks down the title so the element:
//>AX225014 Equine influenza virus H3N8 // 1 (PB2)
//ATGAAGACAACCATTATTTTGATACTACTGACCCATTGGGTCTACAGTCAAAACCCAACCAGTGGCAACA
//GGCATGTCCGCAAACGATTTGCAGACCAAGAACTGGGTGATGCCCCATTCCTTGACCGGCTTCGCCGAGA
//comes out as AX225014
String Acc = Accession(Gene1.get(i));
//seq takes the same element as above and returns only
//ATGAAGACAACCATTATTTTGATACTACTGACCCATTGGGTCTACAGTCAAAACCCAACCAGTGGCAACA
//GGCATGTCCGCAAACGATTTGCAGACCAAGAACTGGGTGATGCCCCATTCCTTGACCGGCTTCGCCGAGA
String seq = trimHeader(Gene1.get(i));
for(int x = 0; x<Pal.size(); x++)
{
if(seq.contains(Pal.get(x))){
String match = (Pal.get(x) + " in organism: " + Acc + " Was found in position: "+ seq.indexOf(Pal.get(x)) + " and at " +seq.lastIndexOf(Pal.get(x)));
printwriter.println(match);
PalindromesSpotted.add(match);
}
}
}
Collections.sort(PalindromesSpotted);
return PalindromesSpotted;
}
First off, your code won't write to any file to log the results since you don't close your writers or at the very least flush PrintWriter. As a matter of fact you don't close your reader as well. You really should close your Readers and Writers to free resources. Food for thought.
You can make your PB2Scan() method return either a simple result list as it does now, or a result list of just acc's which contain the same Pal(s), or perhaps both where a simple result list is logged and at the end of that list a list of acc's which contain the same Pal(s) which will also be logged.
Some additional code and an additional integer parameter for the PB2Scan() method would do this. For the additional parameter you might want to add something like this:
public static ArrayList<String> PB2Scan(ArrayList<String> Pal, int resultType)
throws FileNotFoundException, IOException
{ .... }
Where the integer resultType argument would take one of three integer values from 0 to 2:
0 - Simple result list as the code currently does now;
1 - Acc's that match Pal's;
2 - Simple result list and Acc's that Match Pal's at the end of result list.
You should also really have the file to read as an argument for the PB2Scan() method since this file could very easily be a different name the next go around. This makes the method more versatile rather than if the name of the file was hard-coded.
public static ArrayList<String> PB2Scan(String filePath, ArrayList<String> Pal, int resultType)
throws FileNotFoundException, IOException { .... }
The method can always write the Same output file since it would best suit what method it came from.
Using the above concept rather than writing to the output file (PB2Out.txt) as the PalindromesSpotted ArrayList is being created I think it's best to write the file after your ArrayList or ArrayLists are complete. To do this another method (writeListToFile()) is best suited to carry out the task. To find out if any same Pal's match other Acc's it is again a good idea to have yet another method (getPalMatches()) do that task.
Since the index locations of of more than one given Pal in any given Seq was not reporting properly either I have provided yet another method (findSubstringIndexes()) to quickly take care of that task.
It should be noted that the code below assumes that the Seq acquired from the trimHeader() method is all one single String with no Line Break characters within it.
The reworked PB2Scan() method and the other above mentioned methods are listed below:
The PB2Scan() Method:
public static ArrayList<String> PB2Scan(String filePath, ArrayList<String> Pal, int resultType)
throws FileNotFoundException, IOException {
// Make sure the supplied result type is either
// 0, 1, or 2. If not then default to 0.
if (resultType < 0 || resultType > 2) {
resultType = 0;
}
ArrayList<String> PalindromesSpotted = new ArrayList<>();
File file = new File(filePath);
Scanner sc = new Scanner(file);
sc.useDelimiter(">");
//initializes the ArrayList
ArrayList<String> Gene1 = new ArrayList<>();
//Loads the Array List
while (sc.hasNext()) {
Gene1.add(sc.next());
}
sc.close(); // Close the read in text file.
for (int i = 0; i < Gene1.size(); i++) {
//Acc breaks down the title so the element:
//>AX225014 Equine influenza virus H3N8 // 1 (PB2)
//ATGAAGACAACCATTATTTTGATACTACTGACCCATTGGGTCTACAGTCAAAACCCAACCAGTGGCAACA
//GGCATGTCCGCAAACGATTTGCAGACCAAGAACTGGGTGATGCCCCATTCCTTGACCGGCTTCGCCGAGA
//comes out as AX225014
String Acc = Accession(Gene1.get(i));
//seq takes the same element as above and returns only
//ATGAAGACAACCATTATTTTGATACTACTGACCCATTGGGTCTACAGTCAAAACCCAACCAGTGGCAACA
//GGCATGTCCGCAAACGATTTGCAGACCAAGAACTGGGTGATGCCCCATTCCTTGACCGGCTTCGCCGAGA
String seq = trimHeader(Gene1.get(i));
for (int x = 0; x < Pal.size(); x++) {
if (seq.contains(Pal.get(x))) {
String match = Pal.get(x) + " in organism: " + Acc +
" Was found in position(s): " +
findSubstringIndexes(seq, Pal.get(x));
PalindromesSpotted.add(match);
}
}
}
// If there is nothing to work with get outta here.
if (PalindromesSpotted.isEmpty()) {
return PalindromesSpotted;
}
// Sort the ArrayList
Collections.sort(PalindromesSpotted);
// Another ArrayList for matching Pal's to Acc's
ArrayList<String> accMatchingPal = new ArrayList<>();
switch (resultType) {
case 0: // if resultType is 0 is supplied
writeListToFile("PB2Out.txt", PalindromesSpotted);
return PalindromesSpotted;
case 1: // if resultType is 1 is supplied
accMatchingPal = getPalMatches(PalindromesSpotted);
writeListToFile("PB2Out.txt", accMatchingPal);
return accMatchingPal;
default: // if resultType is 2 is supplied
accMatchingPal = getPalMatches(PalindromesSpotted);
ArrayList<String> fullList = new ArrayList<>();
fullList.addAll(PalindromesSpotted);
// Create a Underline made of = signs in the list.
fullList.add(String.join("", Collections.nCopies(70, "=")));
fullList.addAll(accMatchingPal);
writeListToFile("PB2Out.txt", fullList);
return fullList;
}
}
The findSubstringIndexes() Method:
private static String findSubstringIndexes(String inputString, String stringToFind){
String indexes = "";
int index = inputString.indexOf(stringToFind);
while (index >= 0){
indexes+= (indexes.equals("")) ? String.valueOf(index) : ", " + String.valueOf(index);
index = inputString.indexOf(stringToFind, index + stringToFind.length()) ;
}
return indexes;
}
The getPalMatches() Method:
private static ArrayList<String> getPalMatches(ArrayList<String> Palindromes) {
ArrayList<String> accMatching = new ArrayList<>();
for (int i = 0; i < Palindromes.size(); i++) {
String matches = "";
String[] split1 = Palindromes.get(i).split("\\s+");
String pal1 = split1[0];
// Make sure the current Pal hasn't already been listed.
boolean alreadyListed = false;
for (int there = 0; there < accMatching.size(); there++) {
String[] th = accMatching.get(there).split("\\s+");
if (th[0].equals(pal1)) {
alreadyListed = true;
break;
}
}
if (alreadyListed) { continue; }
for (int j = 0; j < Palindromes.size(); j++) {
String[] split2 = Palindromes.get(j).split("\\s+");
String pal2 = split2[0];
if (pal1.equals(pal2)) {
// Using Ternary Operator to build the matches string
matches+= (matches.equals("")) ? pal1 + " was found in the following Accessions: "
+ split2[3] : ", " + split2[3];
}
}
if (!matches.equals("")) {
accMatching.add(matches);
}
}
return accMatching;
}
The writeListToFile() Method:
private static void writeListToFile(String filePath, ArrayList<String> list, boolean... appendToFile) {
boolean appendFile = false;
if (appendToFile.length > 0) { appendFile = appendToFile[0]; }
try {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath, appendFile))) {
for (int i = 0; i < list.size(); i++) {
bw.append(list.get(i) + System.lineSeparator());
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
You should probably create aMap<String, List<String>> containing the Pals as keys and the Accs that contain them as values.
Map<String, List<String>> result = new HashMap<>();
for (String gene : Gene1) {
List<String> list = new ArrayList<>();
result.put(gene, list);
for (String pal : Pal) {
if (acc.contains(trimHeader(gene))) {
list.add(pal);
}
}
}
Now you have a Map that you can query for the Pals every Gene contains:
List<String> containedPals = result.get(gene);
This is a very reasonable result for a function like this. What you do afterwards (ie the writing into a file) should better be done in another function (that calls this one).
So, this is probably what you want to do:
List<String> genes = loadGenes(geneFile);
List<String> pals = loadPal(palFile);
Map<String, List<String>> genesToContainedPal = methodAbove(genes, pals);
switch (resultTyp) {
// ...
}
I'm very new to Java creating a software application that allows a user to input text into a field and the program runs through all of the text and identifies what the most common word is. At the moment, my code looks like this:
JButton btnMostFrequentWord = new JButton("Most Frequent Word");
btnMostFrequentWord.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String text = textArea.getText();
String[] words = text.split("\\s+");
HashMap<String, Integer> occurrences = new HashMap<String, Integer>();
for (String word : words) {
int value = 0;
if (occurrences.containsKey(word)) {
value = occurrences.get(word);
}
occurrences.put(word, value + 1);
}
JOptionPane.showMessageDialog(null, "Most Frequent Word: " + occurrences.values());
}
}
This just prints what the values of the words are, but I would like it to tell me what the number one most common word is instead. Any help would be really appreciated.
Just after your for loop, you can sort the map by value then reverse the sorted entries by value and select the first.
for (String word: words) {
int value = 0;
if (occurrences.containsKey(word)) {
value = occurrences.get(word);
}
occurrences.put(word, value + 1);
}
Map.Entry<String,Integer> tempResult = occurrences.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.findFirst().get();
JOptionPane.showMessageDialog(null, "Most Frequent Word: " + tempResult.getKey());
For anyone who is more familiar with Java, here is a very easy way to do it with Java 8:
List<String> words = Arrays.asList(text.split("\\s+"));
Collections.sort(words, Comparator.comparingInt(word -> {
return Collections.frequency(words, word);
}).reversed());
The most common word is stored in words.get(0) after sorting.
I would do something like this
int max = 0;
String a = null;
for (String word : words) {
int value = 0;
if(occurrences.containsKey(word)){
value = occurrences.get(word);
}
occurrences.put(word, value + 1);
if(max < value+1){
max = value+1;
a = word;
}
}
System.out.println(a);
You could sort it, and the solution would be much shorter, but I think this runs faster.
You can either iterate through occurrences map and find the max or
Try like below
String text = textArea.getText();;
String[] words = text.split("\\s+");
HashMap<String, Integer> occurrences = new HashMap<>();
int mostFreq = -1;
String mostFreqWord = null;
for (String word : words) {
int value = 0;
if (occurrences.containsKey(word)) {
value = occurrences.get(word);
}
value = value + 1;
occurrences.put(word, value);
if (value > mostFreq) {
mostFreq = value;
mostFreqWord = word;
}
}
JOptionPane.showMessageDialog(null, "Most Frequent Word: " + mostFreqWord);
I have 2 arrays which values are words, each word in the first table is associated with a text (String), now each word from second table is showing how many times (int) is repeating in text (String). The expected table should to be like:
This is the code that I've written so far:
keyW = txtKeyword.getText();
search = textField.getText();
System.out.println("String for car = " + search);
System.out.println("String keyword = " + keyW);
btnUpload.setEnabled(false);
btnNewButton_1.setEnabled(false);
btnNewButton.setEnabled(false);
txtKeyword.setEnabled(false);
textField.setEditable(false);
//waitLabel.setVisible(true);
int iar = 0;
int item;
Map<String, Integer> dictionary = new HashMap<String, Integer>();
String[] searchArray = search.split(",");
String[] itemsFromArray1 = new String[searchArray.length];
//Keyword1 = ("Searched Key"+ "\r\n\t ");
//listKeys.add(Keyword1);
for (iar = 0; iar < searchArray.length; iar++) {
itemsFromArray1[iar] = searchArray[iar].trim();
Keyword1 = (searchArray[iar]);
//listKeys.add(Keyword1);
}
String[] items = keyW.split(",");
for (item = 0; item < searchArray.length; item++) {
WebDriver driver = new HtmlUnitDriver();
((HtmlUnitDriver) driver).setJavascriptEnabled(true);
driver.get("https://en.wikipedia.org/wiki/" + searchArray[item]);
tstr1 = driver.findElement(By.xpath("//*[#id='content']")).getText();
driver.quit();
String[] itemsFromArray = new String[items.length];
for (int i = 0; i < items.length; i++) {
itemsFromArray[i] = items[i].trim();
}
for (String string : itemsFromArray) {
int i = countWords(tstr1, string);
dictionary.put(searchArray[item].concat(string), i);
System.out.println("ARRAY " + dictionary);
}
}
private static int countWords(String tstr1, String string) {
tstr1 = tstr1.toLowerCase();
string = string.toLowerCase();
int posCount = 0;
String positive = string;
Pattern positivePattern = Pattern.compile(positive);
Matcher matcher = positivePattern.matcher(tstr1);
while (matcher.find()) {
posCount++;
}
return posCount;
}
I tried to achieve this with Map<String, Integer> dictionary = new HashMap<String, Integer>(); but the results (dictionary.put(searchArray[item], i);) are wrong. Can anyone give me an idea how to solve this. Thanks!
****UPDATE****
Now the results in the console is something like this:
ARRAY { boyanimal=4, catfree=18, catanimal=60, boyfree=2, catgender=0, boygender=6, windowfree=5}
ARRAY { boyanimal=4, catfree=18, catanimal=60, boyfree=2, windowanimal=4, catgender=0, boygender=6, windowfree=5}
ARRAY { boyanimal=4, catfree=18, catanimal=60, boyfree=2, windowanimal=4, catgender=0, boygender=6, windowgender=0, windowfree=5}
There are values that are repeting. How to make to show just like a table?
Try using this:
Map<String, Integer> tableMap = new HashMap<String, Integer>();
keep the key as:
tableMap.put("Word1-Search1",23);
Using this, you will always have a unique combination for each key.
I hope you don't want to store the data in a data structure? Instead you should use a 2 dimensional String array to store it.
Answering your latest update:
I think you're getting multiple copies because of this line.
dictionary.put(searchArray[item].concat(string), i);
I think the concat is being applied to the entire row of elements. I would use my debugger to analyze this and see what the value of searchArray[item] is and what the value of string is.
what I want to do:
I want to extract every string from a string array to a different string variable.
Outputting this to the console is no problem of course, just iterate over the array.
But when it comes to assigning each value to a different variable, I dont get any further right now. All I found online were suggestions on how to concatenate each index of the array. That is not what I want. I had a similar solution for ints some time ago, but I cannot come up with it right now.
int answerPackagerCounter = 0;
String answerPackager = "answer" + answerPackagerCounter;
String answer0 = "";
String answer1 = "";
String answer2 = "";
String answer3 = "";
boolean correct0 = false;
boolean correct1 = false;
boolean correct2 = false;
boolean correct3 = false;
for(int k = 0; k < answers.size(); k++ ){
answerPackager = answers.get(k);
}
Of course this does not work, since each time answerPackager is overwritten. I'm quite sure not much is missing here, but I can't see it right now.
Any input is appreciated, thanks in advance!
What I've read is that a Map is probably the best way to go. Where the key can be treated as your separate variable and the value of each key is the value.
You probably would want to create an string array of answer & correct variables that will hole answer0, answer1, etc... & correct0, correct1, etc... That way you can avoid hardcoding
public static void main(String[] args) throws Exception {
String[] answers = new String[] { "Blah1", "Blah2", "Blah3", "Blah4" };
String[] correct = new String[] { "false", "true", "false", "false" };
Map<String, String> answersCorrect = new HashMap();
for (int i = 0; i < answers.length; i++) {
answersCorrect.put("answer" + i, answers[i]);
}
for (int i = 0; i < correct.length; i++) {
answersCorrect.put("correct" + i, correct[i]);
}
// Keys are not stored in order of setting
for (String key : answersCorrect.keySet()) {
System.out.println("Key: " + key + " Value: " + answersCorrect.get(key));
}
System.out.println("");
// Direct usage
System.out.println(answersCorrect.get("answer0") + " " + answersCorrect.get("correct0"));
}
Results:
How about making two arrays, String[] answer = new String[4]; Boolean[] correct= new Boolean[4];
Better, create a class like this:
public Class Answers {
private String[] answer = new String[4];
private Boolean[] correct= new Boolean[4];
... Usuals getters and setters...
}