I'm wondering what kind method should I use to search the elements in an array and what data structure to store the return value
For example a txt file contains following
123 Name line Moon night table
124 Laugh Cry Dog
123 quote line make pet table
127 line array hello table
and the search elements are line+table
I read every line as an string and then spilt by space
the output should like this
123 2 (ID 123 occurs twice that contains the search elements)
127 1
I want some suggestions of what kind method to search the elements in the array and what kind data structure to store the return value (the ID and the number of occurs. I'm thinking hashmap)
Read the text file and store each line that ends with table in ArrayList<String>. Then use contains for each element in ArrayList<String>. Store result in HashMap<key,value> where key is ID and value is Integer which represent number of times ID occurs.
First, I would keep reading through the file line by line, there's really no other way of going about it other than that.
Second, to pick out the rows to save, you don't need to do the split (assumption: they all end in (space)table). You can just get them by using:
if (line.endsWith(" table"))
Then, I would suggest using a Map<String, Integer> datatype to store your information. This way, you have the number of the table (key) and how many times if was found in the file (value).
Map<String, Integer> map = new HashMap<String, Integer>();
....reading file....
if (line.endsWith(" table")) {
String number = line.substring(0, line.indexOf(" "))
if (!map.containsKey(number)) {
map.put(number, 1);
} else {
Integer value = map.get(number);
value++;
map.put(number, value);
}
}
Related
The request is simple in words, but then it took a twist
Basically what I need is not only to split a string, but save the"symbols"and later be able to show them
Here's how it works:
Input:
Once upon a time there was a kingdom far, far away
On this kingdom lived a princess
And she was happy by herself
Output:
Once, 1 time, line 1-column 1
upon, 1 time, line 1-column 6
a, 3 times, line 1-column 11, line 1-column 28, line 2-column 23
...
Also should be able to : not consider spaces, \n and \f on them, but like do consider the "," so splitting by spaces would not give "far," and "far" as different symbols, just as "," is a symbol on it's own
Is there any way on which the split method could consider multiple parameters?
Not to mention I am not sure if there is a better way than a for loop to count the line and column on which each "symbol" is repeated
Split the string into symbols, keep the symbols as keys in the hash map and their count in corresponding hash map values.
Example:
Map<String, Integer> tokensWithCounts = new HashMap<String, Integer>();
String[] tokens = str.split("\\s*[a-zA-Z]+\\s*");
List<String> tokensList = Arrays.asList(tokens);
for(String token : tokenList){
if(tokensWithCounts.get(token) == null){
tokensWithCounts.put(token, 0);
}
tokensWithCounts.put(token, tokensWithCounts.get(token) + 1);
}
EDIT: Sorry, I got the question wrong. You will keep the values in a HashMap<String, List<String>>. Tokens will still be keys, List will have all occurrences of the token in the form of "line 1-column 1". The count of occurrences is the .size() of the List<String> that is stored in the HashMap.
I am trying to find a string from messages.properties in an errorMessage and if the errorMessage has the string I need to replace it with corresponding value
I have messages.properties as below
inv_date=INVOICE DATE
inv_id=INVOICE NUMBER
cl_id=CLIENT ID
lf_matter_id=LAW FIRM MATTER ID
inv_total_net_due=INVOICE TOTAL
(inv_start_date|invoice start date)=BILLING START DATE
(inv_end_date|invoice end date)=BILLING END DATE
inv_desc=INVOICE DESCRIPTION
units=LINE ITEM NUMBER OF UNITS
discount_amount=LINE ITEM ADJUSTMENT AMOUNT
total_amount=LINE ITEM TOTAL
(charge_date|charge date)= LINE ITEM DATE
acca_task=LINE ITEM TASK CODE
acca_expense=LINE ITEM EXPENSE CODE
acca_activity= LINE ITEM ACTIVITY CODE
(tk_id|time keeper id)=TIMEKEEPER ID
charge_desc=LINE ITEM DESCRIPTION
lf_id=LAW FIRM ID
(BaseRate|Rate|tk_rate)=LINE ITEM UNIT COST
tk_level=TIMEKEEPER CLASSIFICATION
cl_matter_id=CLIENT MATTER ID
My errorMesage can have any of the (left side)string and I need to replace it with right side string value
Below are couple of sample error messages
String errorMesage1 = "Line 3 : Could not parse inv_date value"
String errorMesage2 = "Line : 1 BaseRate is a required field"
below is my method which conversts the error message
public static String toUserFriendlyErrorMessage(String message) {
ResourceBundle rb = ResourceBundle.getBundle("messages");
for(String key : rb.keySet()){
String header = rb.getString(key);
if(message.contains(key)) {
return message.replaceAll(key, rb.getString(key));
}
}
return message;
}
Below is the expected output:
for errorMessage1 it works fine
System.out.println(toUserFriendlyErrorMessage(errorMessage1)); ==> Line 3 : Could not parse INVOICE DATE value
But for errorMessage2 its not working. It doesnt replace BaseRate with LINE ITEM UNIT COST
System.out.println(toUserFriendlyErrorMessage(errorMessage2)); ==> Line : 1 BaseRate is a required field
Is there a way to find the occurance of multiple strings and replace it with its corresponding value?
For example: Find (BaseRate|Rate|tk_rate) and replace the string with LINE ITEM UNIT COST
Also am wondering can this method simplified further in java 8?
I think you should reconsider your design and use individual keys for the several "aliases" - or probably even better: No aliases at all and just one key per replacement. The problem is that the keys in those properties files are not supposed to contain spaces -- parantheses or not -- so the files are not parsed correctly. If you print the keys, you will see that they are truncated at the first space, e.g. (inv_start_date|invoice start date) becomes (inv_start_date|invoice.
Of course, this also means that, even if you split those "aliases" into separate keys, you can not have keys like invoice start date, as it still contains spaces and will not be parsed correctly.
You could just put those replacements into a regualr Map in your Java source code:
static Map<String, String> replacements = new HashMap<>();
static {
replacements.put("inv_date", "INVOICE DATE");
replacements.put("(BaseRate|Rate|tk_rate)", "LINE ITEM UNIT COST");
// ... more stuff ...
}
Or parse the file manually, splitting the strings at = and putting them into a Map.
And since keys like (BaseRate|Rate|tk_rate) are in fact valid regular expressions, you can just use replaceAll to replace them in all their variants. If they are not contained in the string, replaceAll will just do nothing, so the contains check is not really necessary.
public static String toUserFriendlyErrorMessage(String message) {
for (String key : replacements.keySet()) {
message = message.replaceAll(key, replacements.get(key));
}
return message;
}
Example output:
Line 3 : Could not parse INVOICE DATE value
Line : 1 LINE ITEM UNIT COST is a required field
Or, if you want to use some "Java 8 magic", you could use reduce, but personally, I think the loop is more readable.
return replacements.keySet().stream()
.reduce(message, (s, k) -> s.replaceAll(k, replacements.get(k)))
.toString();
I must convert a text file into a list of strings separated by commas (with no whitespace and no first line). After printing that, I need to print the name of each state, how many lines contain each state, The sum of all Cen2010 values (the 1st number in each line) for each state, sum of Est2013 values (the last number in each line) for each state, and the total change from Cen2010 population to Est2013 population for each state.
Text File Example:
NAME,STNAME,Cen2010,Base2010,Est2010,Est2011,Est2012,Est2013
"Abingdon city",Illinois,3319,3286,3286,3270,3242,3227
"Addieville village",Illinois,252,252,252,250,250,247
"Addison village",Illinois,36942,36964,37007,37181,37267,37385
"Adeline village",Illinois,85,85,85,84,84,83
Current Code:
def readPopest():
censusfile=pickAFile()
cf=open(censusfile,"rt")
cflines=cf.readlines()
for i in range(len(cflines)-1):
lines=cflines[i+1]
estimate=lines.strip().split(',')
print estimate
Returning:
['"Abingdon city"', 'Illinois', '3319', '3286', '3286', '3270', '3242', '3227']
['"Addieville village"', 'Illinois', '252', '252', '252', '250', '250', '247']
['"Addison village"', 'Illinois', '36942', '36964', '37007', '37181', '37267', '37385']
['"Adeline village"', 'Illinois', '85', '85', '85', '84', '84', '83']
I think you can import this data to SQL database and then it is very easy to sum, filter etc.
But in Python we have dictionaries. You can read data and fill dictionary where key name is name of the state. Then for each line you add town to list of towns in this state, and add numbers to already saved numbers. Of course for 1st town in state you must create structure with two arrays. One for towns, and one for numbers. In code it looks like:
def add_items(main_dict, state, town, numbers):
try:
towns_arr, numbers_arr = main_dict[state]
towns_arr.append(town)
for i in range(len(numbers)):
numbers_arr[i] += numbers[i]
except KeyError:
town_arr = [town, ]
main_dict[state] = [town_arr, numbers]
Now you must use it in your main code that reads file:
state_dict = {}
cf = open(censusfile, "rt")
lines = cf.readlines()
for line in lines[1:]: # we skip 1st line
arr = line.strip().split(',')
town = arr[0]
state = arr[1]
numbers = [int(x) for x in arr[2:]]
add_items(state_dict, state, town, numbers)
print(state_dict)
As a homework try to print this dictionary in desired format.
I have a text file of n columns and n rows separated by tab space.. How do i use split function to store the columns and rows into a hashmap.Please help.My text file will be like..
Dept Id Name Contact
IT 1 zzz 678
ECE 2 ttt 789
IT 3 rrr 908
I tried the following.But it dint work.
Map<String,String> map=new HashMap<String,String>();
while(lineReader!=null)
{
String[] tokens = lineReader.split("\\t");
key = tokens[0];
values = tokens[1];
map.put(key , values );
System.out.println("ID:"+map.get(key ));
System.out.println("Other Column Values:"+map.get(values ));
}
This returns the key of the last entry(row) of the file and value as null. But i need to store all rows and columns in the map. How do i do it?
If I understand your data correctly,
After
String[] tokens = lineReader.split("\\t");
is processed on the first line, you'd have 4 tokens in the array.
I think you are using wrong logic, if you want to store the map in the following way:
IT -> (1 ZZZ 678)
.... etc then you need to process the data differently.
What you are storing in the map is follows:
IT -> 1
ECE -> 2
...
and so on.
That's why you get null when you are trying to do:
map.get(value);
What you should instead print is the Key and map.get(key).
Actually, in any case I don't think Map is what you want (but I don't know what you really want).
For now though, for your understanding of this problem try printing:
System.out.println("Total collumns: "+ tokens.length);
Updated:
This should work for you. It isn't the most elegant implementation for what you want, but gets the job done. You should try improving it from here on.
Map<String,String> map=new HashMap<String,String>();
while(lineReader!=null)
{
String[] tokens = lineReader.split("\\t");
key = tokens[1];
values = tokens[2]+tokens[3];
map.put(key , values );
System.out.println("ID:"+key);
System.out.println("Other Column Values:"+map.get(key));
}
Good luck!
Assume I'm taking input a string from command line and I want to find the duplicate and unique entries in the string by using Hashtable.
eg:
i/p:
hi hello bye hi good hello name hi day hi
o/p:
Unique elements are: bye, good, name, day
Duplicate elements are:
hi 3 times
hello 2 times
You can break the input apart by calling split(" ") on the input String. This will return a String[] representing each word. Iterate over this array, and use each String as the key into your Hashtable, with the value being an Integer. Each time you encounter a word, either increment its value, or set the value to 0 if no value is currently there.
Hashtable<String, Integer> hashtable = new Hashtable<String, Integer>();
String[] splitInput = input.split(" ");
for(String inputToken : splitInput) {
Integer val = hashtable.get(inputToken);
if(val == null) {
val = new Integer(0);
}
++val;
hashtable.put(inputToken, val);
}
Also, you may want to look into HashMap rather than Hashtable. HashMap is not thread safe, but is faster. Hashtable is a bit slower, but is thread safe. If you are trying to do this in a single thread, I would recommend HashMap.
Use a hashtable with string as key and a numeric type as counter.
Go through all the words and if they are not in the map, insert them; otherwise increase the count (the data part of the hashtable).
hth
Mario
you can convert each string into an integer. Then, use the generated integer as the hash value. To convert string to int, you can treat it as a base 256 number and then convert it