I use ArrayList for my Dictionary Index Data
I want to make similar search system
for example
dictionary data : 'abcd' 'bcde' 'cdef' 'fghi' 'ijkl'
if i search 'cd' i want to get index '3'
in my source
for (String st : wordList) {
if (st.indexOf(searchWord) == 0) {
ListView.setSelection(index); //set listView scroll
break;
}
index++;
}
but it took too much time :(
what is the best way to make this system?
just remove index++ from loop and change if(CONDITION) like this.
for (String st : wordList) {
if (st.startsWith(searchWord)) {
System.out.println("position="+wordlist.indexOf(st));//display index in log
ListView.setSelection(wordlist.indexOf(st)); //set listView scroll
break;
}
}
Divide and Rule :)
Rather than storing all dictionary data into single list .... create array list for each Char like a,b,c,d (you will have total 26 list : one is for each alphabet)
Map<Character, List<String>> map = new HashMap<Character, List<String>>();
// creating list for each char
for(int i=0;i<26;i++){
char ch = (char) ('a' + i);
map.put(ch,new ArrayList<String>());
}
// storing some sample dictionary data or make a function for it
map.get("abcd".charAt(0)).add("abcd");
map.get("bcde".charAt(0)).add("bcde");
map.get("cdef".charAt(0)).add("cdef");
map.get("fghi".charAt(0)).add("fghi");
map.get("ijkl".charAt(0)).add("ijkl");
String searchWord = "cd";
// searh the given String
List<String> wordList =map.get(searchWord.charAt(0));
int idx =0;
for (String st : wordList) {
if (st.startsWith(searchWord)) {
idx = wordList.indexOf(st);
System.out.println("position="+idx); //display index in log
break;
}
}
// if require, In idx variable : add the size() of all list
// which come before the give searh char
// ListView.setSelection(idx); //set listView scroll
}
Note : please convert the upper case word to lower case before searching or storing.
Related
I have to put in a string array some values resulting from several parsed html pages. So the first value it's a name and all the others are numbers. After I must return the array to main to print. Obviously I make something wrong .
this is part of my newbie code...
String[] ret = null;
int y = 0;
for (Element h1 : h1s) {
// Using Jsoup to scrape the html file and find H1 text
h1_id = h1.className();
// I put here the text of H1
h1_text = h1.text();
if (h1_id.equals("ezomat-logo-text ezCSS")) {
// jump to the next h1
} else {
// I want to put the txt as the first array place
ret[y] = "'" + h1_text + "'";
}
i = 0;
// found the number values single integers with comma
for (Element image : images) {
Imm[i] = "," + imageName;
i++;
}
i = 0;
y = 1;
// y = 1 because I want to start from the second position.
for (Element image : images) {
ret[y] = Imm[i];
i++;
y++;
}
}
return ret;
You can't dynamicly resize an array, you have to initialize it with a fixed size.
So, you have to initialize it with
String[] ret = new String[size];
where size have to be the number of elements you are going to put into your array.
Or the better approach: Use ArrayList<String>instead. Initialize it with
ArrayList<String> ret = new ArrayList<String>();
and add your Items with ret.add("whatever");.
On the first line of your code you attempt to define an array without a size, but you don't actually define it, you just assign null.
Also, it's impossible to dynamically add elements to such array.
For these scenarios we have List.
To define a List that stores Strings use the following code:
List<String> ret = new ArrayList<String> ();
And then proceed to add elements to this array like so:
ret.add ("," + imageName);
To retrieve a value from an index in the list do the following:
ret.get(index);
Java does not allow arrays with variable length. I think that this is your main problem.
There are two choiches:
Obtain the array length first and instantiate the array accordingly
String[] ret = new String[100];
Use an ArrayList
ArrayList<String> ret = new ArrayList<String>();
You can add elements to the ArrayList like this: ret.add(value);
The Java Tutorial: Arrays
java.util.ArrayList reference
I'm trying to write a program that takes in a text file as input, adds words in it as keys and the associated to the words values schould be page numbers they are located in. Text looks like this:
Page1
blah bla bl
Page2
some blah
So for word "blah" output must be
blah : [1,2].
I only inserted the keys, but I can't figure out how to insert associated values to them. Here's what I have so far:
BufferedReader reader = new BufferedReader(input);
try {
Map <String, List<Integer>> library
= new TreeMap<String, List<Integer>>();
String line = reader.readLine();
while (line != null) {
String[] tokens = line.trim().split("\\s+");
for (int i = 0; i < tokens.length; i++) {
String word = tokens[i];
if (!library.containsKey(word)
&& !word.startsWith("Page")) {
library.put(word, new LinkedList<Integer>());
if (tokens[0].startsWith("Page")
&& library.containsKey(word)) {
List<Integer> pages = library.get(word);
int page = getNum(tokens[0]);
pages.add(page);
page++;
}
}
}
}
line = reader.readLine();
}
}
To get number of page I use this method
private static int getNum(String s) {
int result = 0;
int p = 1;
int i = s.length() - 1;
while (i >= 0) {
int d = s.charAt(i) - '0';
if (d >= 0 && d <= 9) {
result += d * p;
} else {
break;
}
i--;
p *= 10;
}
return result;
}
Thank's for all Your ideas!
The pages variable is declared inside the scope of your inner if statement. Once that block ends the variable is out of scope and undefined. If you want to use the list of pages later then it needs to be declared as a class variable.
I assume you are using pages to later generate a table of contents. But it's not strictly necessary as you can generate it later from your word index - I'll demonstrate how to do that below.
You also need to declare a currentPage variable which hold the latest 'PageN' text you have seen. There's no need to increment this manually: you should just store the number in the text (which copes with blank pages).
Page numbers seem to always be on their own line so page detection should be on the line text not on the word (which copes with situations where a line reads 'for more information see Page72').
It's also worth checking that there's a valid page number before your first word.
So putting that all together your code should be structured something like the following:
Map<String, Set<Integer>> index = new TreeMap<>();
int currentPage = -1;
String currentLine;
while ((currentLine = reader.readLine()) != null) {
if (isPage(currentLine)) {
currentPage = getPageNum(currentLine);
} else {
assert currentPage > 0;
for (String word: words(currentLine)) {
if (!index.contains(word))
index.put(word, new TreeSet<>());
index.get(word).add(currentPage);
}
}
}
I've separated methods words, isPage and getPageNum but you seem to have working code for all of those.
I've also changed the List of pages to a Set to reflect the fact that you only want a word-page reference once in the index.
To get an ordered list of all pages from the index use:
index.values().stream()
.flatMap(List::stream).distinct().sorted()
.collect(Collectors.toList());
That's assuming Java8 but it's not too hard to convert if you don't have streams.
If you are going to generate a reverse index (pages to words) then for efficiency reasons you should probably create the reverse map (Map<Integer, List<String>>) as you are processing the words.
You should try something like this. I'm not totally sure how you're using the pages, but this code will check if library contains the word (like you already have) and then if it doesn't it will add the page number to the list for that word.
if (!library.containsKey(word) && !word.startsWith("Page")) {
library.put(word, new LinkedList<Integer>());
}
else {
library.put(word, library.get(word).add(page));
}
Your problem seems to be in this piece of logic:
if (tokens[0].startsWith("Page")
&& library.containsKey(word)) {
clearly you are adding page numbers only when line starts with Page otherwise the logic inside if condition is not executed so you never updated the page number for any words.
I want to find the index of the start up letter and then show the index of that item in array or array list in java.
Example: I have:
String[] arr={"apple","at","book","bad","car","cat"};
when I input a: then i will get index =0, b: i will get index=2, c: i will get index=4
Because my array item is over 20,000 , so using linear Search is too slow.
and my list is unsorted, so i can't use Binary Search also.
I want to get index of the item like the example above, what can i solve with this?
You can run some initialization code (before the user starts to type letters in).
// initialize an array that has a cell for each letter with value -1
int[] firstIndexes = new int[26];
for(int i=0;i<firstIndexes.length;i++) {
firstIndexes[i] = -1;
}
// loop over original array and look for each letter's first occurence
for(int i=0;i<wordsArray.length;i++) {
char c=wordsArray[i][0];
if(firstIndexes[c-'a'] < 0) {
firstIndexes[c-'a'] = i;
}
}
Then when the user types a letter you just need to find its index in the 'firstIndexes' array.
If you want to get all the indexes of words starting with a certain letter then try this one:
While adding the Words to your Array/list (that will hold all your words) you could also add it to a map that will hold all indexes for every first letters.
Map<String, ArrayList<Integer>> myMap = new HashMap<String, ArrayList<Integer>>();
public void yourmethod() {
//adding all your words to an Array/arraylist goes here. (arr[] in this case)
string firstLetter = yourword.substring(0,1);
if(myMap.constainsKey(firstLetter)) {
myMap.get(letter).add(yourword);
} else {
myMap.put(firstLetter, yourword);
}
}
I'm writing a program that applies many principles of computational linguistics. My problem at this moment is the following piece of code form a method that "flexibilizes two definitions". This is, it compares two different definitions of the same word, and in each definition empty or blank spaces will be added to later on work with the altered definitions (with blank spaces added).
Say we have the following two definitions, defining the term "free fall".
1) Free fall descent of a body subjected only to the action of gravity.
2) Free fall movement of a body in a gravitational field under the influence of gravity
There is a list of words called stoplist, which contains the words: "of", "a", "in", "to", and "under". After the process, each word in the definition that is also contained in the stoplist must correspond to a blank space OR another stoplist word of the other definition. So after executing such process, the previous definitions, represented in two different lists, should look like this:
1) Free fall descent of a body ____ ____ subjected only to the action of gravity.
2) Free fall movement of a body in a gravitational field under the influence of gravity.
The code I wrote to achieve this is the following:
[...]
String[] sList = STOPLIST.split(" "); //this is the stoplist
String[] definition1 = defA1.split(" "); //this is the array of words of the first definition
String[] definition2 = defA2.split(" "); //this is the array of words of the second definition
List<String> def1 = new ArrayList<String>();
List<String> def2 = new ArrayList<String>();
List<String> stopList = new ArrayList<String>();
for(String word : definition1){
def1.add(word); //I transform arrays into lists this way because I used to think that using .asList() was the problem.
}
for(String word : definition2){
def2.add(word);
}
for(String word : sList){
stopList.add(word);
}
int mdef = (def1.size() <= def2.size()) ? def1.size() : def2.size(); //here mdef will have the value of the lenght of the shortest definition, and we are going to use the value of mdef to iterate later on.
for(int i = 0; i < mdef; i++){
if (stopList.contains(def1.get(i))) { //here I check if the first word of the first definition is also found in the stoplist.
if (!stopList.contains(def2.get(i))) { //If the word of def1 previously checked is in the stoplist, as well as the corresponding word in the second definition, then we won't add a " "(blank) space in the corresponding position of the second definition.
def2.add(i , " "); //here I add that blank space, only if the stoplist word in def1 corresponds to a non-stoplist word in def2. Again, we do this so the stoplist word in def1 corresponds to a blank space OR another stoplist word in def2.
if(mdef == def2.size())
mdef++; //In case the shortest definition is the definition to which we just added spaces, we increment mdef++, because that space added increases the length of the shortest definition, and to iterate in this recenlty extended definiton, we have to increment the index with which we iterate.
}
} else if (stopList.contains(def2.get(i))) { //this else if does the same than the previous one, but checks for the second definition instead of the first one. And adds blanks to def1 instead of def2 if necessary.
if (!stopList.contains(def1.get(i))) {
def1.add(i , " ");
if(mdef == def1.size())
mdef++;
}
}
}
[...]
Now, if you analyze the code carefully, you will realize that not all words of the lengthiest list will be checked, given that we iterate ove the definitions using the lenght of the shortest definition as index. This is fine, the remainding words of the lenghtiest definitions don't have to be checked, they will correspond to null spaces of the other definition (in case the lists don't end up being of the same lenght after the addition of spaces, as the previous exaple shows).
Now, after the explanation, the problem is the following: after running the main class, which calls the method that contains the previous code, a runtime exceptions pops out:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:571)
at java.util.ArrayList.get(ArrayList.java:349)
at main2.main(main2.java:75)
I don't understand why it is finding any of the lists as "empty". I have tried to solve it in too many ways, I hope a I gave a good explanation.
It may help as a clue that if I assign mdef to the lengthiest size instead of the shortest, that is :
int mdef = (def1.size() >= def2.size()) ? def1.size() : def2.size();
the error changes to:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 15, Size: 15
at java.util.ArrayList.rangeCheck(ArrayList.java:571)
at java.util.ArrayList.get(ArrayList.java:349)
at asmethods.lcc.turnIntoFlex(lcc.java:55)
at asmethods.lcc.calLcc(lcc.java:99)
at main2.main(main2.java:73)'
Where lcc is the class that contains the method turnIntoFlex that contains the piece of code I'm showing. The line 55 of "turnIntoFlex" corresponds to the first line of the loop, that is:
if (stopList.contains(def1.get(i))) { [...]
Comments: The values of defA1 and defA2 are the definitions, respectively. i.e. def1 and def2, initially, are lists in which each separate element is a word. I can't check if these lists are being populated by printing them because the indexoutofboundsexception pops at the very moment the loop starts. However, I do print the values of the sizes of mdef, def1.size() and def2.size(), and the values turn out to be 13, or 15, showing that no list is empty before the "for" loop starts.
The mdef++ was something I added recently, not to exactly to solve this specific problem, but the error has been popping since before I added the mdef++ part. As I explained, The intention is to increase mdef++ when the shortest list is extended (but only when the short list is extended) so we iterate through all the words of the short list, and not more.
One issue with your code is that when you increment mdef you do not check to see if it now exceeds the length of the other list.
For example, suppose def1 had 3 words and def2 had 4 words. mdef would start at 3. But then suppose you successively add two spaces to def1 and increment mdef twice to be 5. This now exceeds the length of def2 and will then cause an index out of bounds exception in the def2 else condition if you keep iterating up to 5.
Added later:
Another serious issue with your code (that I thought of later) is that when you add the space to a list (either def1 or def2) this shifts the indices of all of the subsequent elements up by 1. So, for example, if you add a space at spot 0 in def1 when i is 0, then on the next pass through the loop, having incremented i to 1, you will look at the same word in def1 that you looked at in the previous pass. This is probably the source of some of your exceptions (as it would lead to a continual loop until you exceed the length of the other list: problem #1 above).
To correct both of these issues, you would need to change your code to something like:
int i = 0;
int j = 0;
while (i < def1.size() && j < def2.size()) {
if (stopList.contains(def1.get(i)) && !stopList.contains(def2.get(j)))
def2.add(j++, " ");
else if (stopList.contains(def2.get(j)) && !stopList.contains(def1.get(i)))
def1.add(i++, " ");
++i;
++j;
}
Note that you don't ned mdef any more in this implementation.
Man, I think I got it. I modified the code, but I hope you understand what I did:
static public void main(String[] argv) {
String[] sList = "of a in to under".split(" ");
String[] definition1 = "Free fall descent of a body subjected only to the action of gravity"
.split(" ");
String[] definition2 = "Free fall movement of a body in a gravitational field under the influence of gravity"
.split(" ");
List<String> def1 = new ArrayList<String>();
List<String> def2 = new ArrayList<String>();
List<String> stopList = new ArrayList<String>();
for (String word : definition1) {
def1.add(word);
}
for (String word : definition2) {
def2.add(word);
}
for (String word : sList) {
stopList.add(word);
}
int mdef = (def1.size() <= def2.size()) ? def1.size() : def2.size(); // Shortest
// length
for (int i = 0; i < mdef; i++) {
System.out.println(i);
if (!stopList.contains(def1.get(i)) && !stopList.contains(def2.get(i))) {
continue;
}
else if (stopList.contains(def1.get(i)) && stopList.contains(def2.get(i))) {
continue;
}
else if (!stopList.contains(def1.get(i)) && stopList.contains(def2.get(i))) {
def1.add(i, " ");
mdef = (def1.size() <= def2.size()) ? def1.size() : def2.size(); // define mdef again
}
else if (stopList.contains(def1.get(i)) && !stopList.contains(def2.get(i))) {
def2.add(i, " ");
mdef = (def1.size() <= def2.size()) ? def1.size() : def2.size(); // define mdef again
}
}
for (String word : def1) {
if (word.equals(" "))
System.out.print("_ ");
else
System.out.print(word+" ");
}
System.out.println();
for (String word : def2) {
if (word.equals(" "))
System.out.print("_ ");
else
System.out.print(word+" ");
}
}
Is this the exact code you're using? I just ran it and it worked fine, I used:
import java.util.*;
public class HelloWorld {
public static void main(String []args) {
String stoplist= "of a in to and under";
String defA1 = "Free fall descent of a body subjected only to the action of gravity";
String defA2 = "Free fall movement of a body in a gravitational field under the influence of gravity";
String[] sList = stoplist.split(" "); //this is the stoplist
String[] definition1 = defA1.split(" "); //this is the array of words of the first definition
String[] definition2 = defA2.split(" "); //this is the array of words of the second definition
List<String> def1 = new ArrayList<String>();
List<String> def2 = new ArrayList<String>();
List<String> stopList = new ArrayList<String>();
for (String word : definition1) {
def1.add(word); //I transform arrays into lists this way because I used to think that using .asList() was the problem.
}
for (String word : definition2) {
def2.add(word);
}
for (String word : sList) {
stopList.add(word);
}
int mdef = (def1.size() <= def2.size()) ? def1.size() : def2.size(); //here mdef will have the value of the lenght of the shortest definition, and we are going to use the value of mdef to iterate later on.
for (int i = 0; i < mdef; i++) {
if (stopList.contains(def1.get(i))) { //here I check if the first word of the first definition is also found in the stoplist.
if (!stopList.contains(def2.get(i))) { //If the word of def1 previously checked is in the stoplist, as well as the corresponding word in the second definition, then we won't add a " "(blank) space in the corresponding position of the second definition.
def2.add(i , " "); //here I add that blank space, only if the stoplist word in def1 corresponds to a non-stoplist word in def2. Again, we do this so the stoplist word in def1 corresponds to a blank space OR another stoplist word in def2.
if (mdef == def2.size())
mdef++; //In case the shortest definition is the definition to which we just added spaces, we increment mdef++, because that space added increases the length of the shortest definition, and to iterate in this recenlty extended definiton, we have to increment the index with which we iterate.
}
} else if (stopList.contains(def2.get(i))) { //this else if does the same than the previous one, but checks for the second definition instead of the first one. And adds blanks to def1 instead of def2 if necessary.
if (!stopList.contains(def1.get(i))) {
def1.add(i , " ");
if (mdef == def1.size())
mdef++;
}
}
}
for (String word : def1) {
System.out.print(word+",");
}
System.out.println();
for (String word : def2) {
System.out.print(word+",");
}
}
}
App reads TextEdit value to String and then converts to ArrayList. But before converting it removes spaces between words in TextEdit. So after converting I get ArrayList size only 1.
So my question is how to get the real size. I am using ArrayList because of its swap() function.
outputStream.setText("");
stream = inputStream.getText().toString().replace(" ", "");
key = Integer.parseInt(inputKey.getText().toString());
List<String> arrayList = Arrays.asList(stream);
int lenght = arrayList.size();
if (key < lenght)
{
outputStream.append(lenght+"\n");
outputStream.append("OK");
}
else {
outputStream.append(lenght+"\n");
outputStream.append("Error");
}
}
stream = inputStream.getText().toString();
key = Integer.parseInt(inputKey.getText().toString());
List<String> arrayList = new ArrayList<String>();
for (String x : stream.split(" ")) arrayList.add(x);
int lenght = arrayList.size();
if (key < lenght)
{
outputStream.append(lenght+"\n");
outputStream.append("OK");
}
else {
outputStream.append(lenght+"\n");
outputStream.append("Error");
}
That is my guess at what you actually wanted to do...
The size and the length are different things.
You try to get the size when you want the length.
Use arrayList[0].length() instead of your arrayList.size().
If you want to parse your String to an Array try:
List<String> arrayList = Arrays.asList(stream.split(","));
(this example expects that your text is a comma separated list)
Arrays.asList() expect an array as paramter not just a String. A String is like an array of String of size 1 thats why your list is always of size 1. If you want to Store the words of your String use :
Arrays.asList(stream.split(" ")); //Don't use replace method anymore