how to group 59 elements into one element in arraylist? - java

so, i have a program that read value and its year from a textfile that starts from 1960 till 2018. each indicator code have different values but the year stays the same, 1960-2018. i have successfully read the textfile and store it in the arraylist.
however, values and its years from one indicator is not grouped in one element. but instead, it groups them one value(and its year), one element. AND let's say i have 2 indicator code, 59 values for each indicator code. they're all mixed up in 118 elements. i wanted them in 2 elements.
how to solve this problem so that each indicator code and its data(years and values) is in one element?
myLinkedList bigdata = new myLinkedList();
ArrayList <MyData> data = new ArrayList();
MyData d1;
File inFile2 = new File ("indicator2.txt");
FileReader fr2 = new FileReader (inFile2);
BufferedReader br2 = new BufferedReader(fr2);
String str2 = br2.readLine();
while(str2 != null ){
StringTokenizer st = new StringTokenizer(str2,";");
String cCode = st.nextToken();
String iName = st.nextToken();
String iCode = st.nextToken();
for (int j = 0; j < 59; j++){
String v = st.nextToken();
int year = 1960 + j;
d1 = new MyData (year,v);
data.add(d1);
}
Indicator idct1 = new Indicator (cCode,iName,iCode,data);
bigdata.insertAtBack(idct1);
str2 = br2.readLine();
}
example of indicator2.txt:
MYS; Employment in industry (% of total employment) (modeled ILO estimate); SL.IND.EMPL.ZS; null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;null;31,72100067;31,62000084;32,01699829;32,22900009;32,34000015;32,23300171;33,6629982;31,76000023;31,70000076;32,18299866;33,11000061;31,97999954;32,02000046;30,12700081;29,72299957;30,26000023;28,45999908;28,68000031;27,01300049;27,73699951;29,08600044;28,56900024;28,36300087;28,02300072;27,51600075;27,48699951;27,39800072;27,30500031
(From left: cCode; iName; iCode; the values starting from 1960)

I believe the problem is that you're writing the data into the same ArrayList over and over again for all indicator codes. What if you moved the following statement:
ArrayList <MyData> data = new ArrayList();
Inside your while loop. Then you would be creating a new ArrayList for each indicator code when your save it to an Indicator object.

Generic types can be nested, so one solution would be to use an ArrayList of ArrayLists of MyData objects instead:
ArrayList<ArrayList<MyData>>

Related

Adding HashSet/Array to HashMap error

I am a beginner at Java, and I'm having trouble understanding why I'm getting an error. I have a .csv file containing cities, provinces, and respective populations of Canada. I have been trying to read the file and then put the PROVINCE and POPULATION values into a HashMap (cana) via a key/value pair. I've created a HashSet (canada) to split up the .csv, and I would like to keep that as-is if possible.
My question is about the cana.add(provSet, pop1). I am getting an "cannot find symbol - method add(java.util.Set) error around the "put", and I can't figure out why. Can someone please help me understand what I've done wrong? Since I am a beginner, additional explanation would be greatly appreciated!
String filename = "canada.csv";
try
{
BufferedReader br = new BufferedReader(new FileReader("canada.csv"));
String line = null;
HashSet<String> canada = new HashSet<String>();
HashMap<Set<String>, Set<Integer>> cana = new HashMap<Set<String>, Set<Integer>>();
while((line=br.readLine())!=null) {
String city = line.split(",")[0];
canada.add(city);
String province = line.split(",")[1];
canada.add(province);
Set<String> provSet = new HashSet<String>(Arrays.asList(province));
String population = line.split(",")[2];
canada.add(population);
int p = new Integer(population);
Set<Integer> pop1 = new HashSet<Integer>(Arrays.asList(p));
cana.add(provSet, pop1); //ERROR
//Trying to find the most populated province
String maxProvince = "";
int maxProvPop = 0;
for(String province : cana.keySet()) {
int provPop = cana.get(province);
System.out.println(population);
if( provPop > maxProvPop )
{
maxProvPop = provPop;
maxProvince = province;
}
System.out.println("The most populated province is " + maxProvince + " with a population of " + maxProvPop);
}
I think you're mixing up the methods for HashSet and HashMap. You use the add method for HashSet, and put method for HashMap.
HashSet Documentation
HashMap Documentation

How I transfer file details to Vector?

I splited the file to String lines and put them in array indexes.
String fileString = readfromfile(fileEvents);
String[] fileLines = fileString.split("\n");
assuming this is the first index in fileLines:
14 57 9 2 www.buytickets.com
this is the constructor:
Orders (int EventID, int SoldtoCustomerID, int SoldtoEmployeesID, int NumberOfTickets, String URL)
the vector instance:
Vector<Orders> myOrders = new Vector<Orders>();
how do I transfer this line to first index in the vecotr so it would be like this:
(14,57,9,2,www.buytickets.com)
thank you :)
If we assume that there won't be any invalid entries the following should do the job:
Vector<Orders> myOrders = new Vector<Orders>();
for (String line : fileLines) {
String[] tokens = line.split("\\s+")
Orders o = new Orders(
Integer.valueOf(tokens[0]),
Integer.valueOf(tokens[1]),
Integer.valueOf(tokens[2]),
Integer.valueOf(tokens[3]),
tokens[4])
myOrders.add(o)
}

Search element in arraylist

How can I search element in arraylist and display it? Example is the user wants to search the code A25 Then it will print the whole content on that arraylist that he search only and the output is A25 CS 212 Data Structures 3.
Subject CS212 = new Subject("A25","\t\tCS 212","\t\tData Structures\t\t\t\t",units);
Subject IT312 = new Subject("A26","\t\tIT 312","\t\tData Base Management System 2\t\t",units);
Subject IT313 = new Subject("A27","\t\tIT 312","\t\tData Base Management System 2\t\t",units);
Subject CS313 = new Subject("A29","\t\tCS 313","\t\tDigital Designt\t\t\t\t",units);
Subject Disc = new Subject("A30","\t\tIT 212","\t\tDiscrete Structurest\t\t",units);
Subject A31 = new Subject("A31","\t\tIT 212","\t\tDiscrete Structurest\t\t",units);
Subject Engl3 = new Subject("984","\t\tEngl 3","\t\tSpeech and oral Communicationt\t\t",units);
Subject Theo3 = new Subject("582","\t\tTheo 3","\t\tChrist and Sacramentst\t\t",units);
Subject Stat = new Subject("470","\t\tStata1","\t\tProbablility and Statisticst\t\t",units);
Subject Dota = new Subject("999","\t\tDota 2","\t\tDota Guide\t\t\t\t",units);
ArrayList<Subject> arrList = new ArrayList<Subject>();
arrList.add(CS212);
arrList.add(IT312);
arrList.add(IT313);
arrList.add(CS313);
arrList.add(Disc);
arrList.add(A31);
arrList.add(Engl3);
arrList.add(Theo3);
arrList.add(Stat);
arrList.add(Dota);
//User input that he wants to search
for(int i = 0; i < 3; i++,num++)
{
System.out.print("\t\t"+num +". ");
codeNo[i] = scan.next();
String output = Character.toUpperCase(codeNo[i].charAt(0)) + codeNo[i].substring(1);
codeNo[i] = output;
}
// This is what I tried but it doesn't work Idk why
for (Subject s : arrList) {
for(int i =0; i < codeNo.length; i++)
if (s.equals(codeNo[i])) {
System.out.println("\t\t\t"+s);
}
}
public Subject(String codeNo, String subjectID, String title , int unit)
{
//Constructor . .
}
//Desired output
Code to search
A25
A26
A27
output
A25 CS 212 Data Structures 3
A26 IT 312 Data Base Management System 2 3
A27 IT 312 Data Base Management System 2 3
You are trying to search an arraylist of subjects, you need to write a small function to compare the code string to the corresponding string of the class. You can do this by adding this to your subject class.
Example :
#Override
public boolean equals(String code) {
return code.equals(this.<compare to member>);
}
and change the compare to member that needs to match the code that you match.
EDIT : Easier way to do is to just change your existing code to :
if (s.code.equals(codeNo[i])) //assuming your code class member is a public string

How to compare array elements that are not parrallel while looping through the lines of a text file?

I am stuck with this logic. I have two text files that the program reads, but I cannot get it to compare each other the following way:
First text file looks like this:
1,01/04/14,apo,14:47:53,
2,01/04/14,apo,14:48:08,
3,01/04/14,apo,14:48:25,
7,01/04/14,apo,14:53:50,
Second text file looks like this:
1,01/04/14,apo,14:47:53,
2,01/04/14,apo,14:48:08,
4,01/04/14,apo,14:48:25,
7,01/04/14,apo,14:53:50,
Each line of text from each file is stored in an array. I want to grab from the first line of the first text file, the first array of the first line which is "1" and compare that to every first array element of each line in the second file. Then grab the first array element of the second line of the first text file which is "2" and compare that to the first array element of each line on the second text file.
This is what I have done so far:
while ( (tkp = tkpbr.readLine()) != null && (tkn = tknbr.readLine()) != null){
tkparray = tkp.split(",");
int c = 0;
for(String s : tkparray){
//System.out.println("values[" + c + "] = " + s);
c++;
}
tknarray = tkn.split(",");
int a = 0;
for(String s : tknarray){
//System.out.println("values[" + a + "] = " + s);
a++;
}
if(tkparray[0].contentEquals(tknarray[0])){
System.out.println(tkparray[0]+"\t"+tknarray[0]);
}
}
This works, but if the array elements are not equal or if the text files look like below it won`t work:
First text file looks like this:
1,01/04/14,apo,14:47:53,
2,01/04/14,apo,14:48:08,
3,01/04/14,apo,14:48:25,
7,01/04/14,apo,14:53:50,
Second text file looks like this:
3,01/04/14,apo,14:47:53,
7,01/04/14,apo,14:48:08,
1,01/04/14,apo,14:48:25,
2,01/04/14,apo,14:53:50,
Any help is greatly appreciated!
There are several ways of doing it.
One is to create a class that modelizes each lines of both files. Assuming each line is unique in a file (looking at the first number), store each lines in two Set and check for equality at the end.
class Date {
private long id;
private Date date;
private String desc;
//constructor and all stuff
//don't forget to override equals and hashcode
}
Set<Data> datasFileOne = new HashSet<>();
Set<Data> datasFileTwo = new HashSet<>();
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
while ((tkp = tkpbr.readLine()) != null && (tkn = tknbr.readLine()) != null){
tkparray = tkp.split(",");
datasFileOne.add(new Data(Long.parseLong(tkparray[0]),
sdf.format(tkparray[1]+" "+tkparray[3]),
tkparray[2]);
//do the same thing for setFileTwo
}
boolean filesEquals = datasFileOne.equals(datasFileTwo);
If you don't care about storing those values in a POJO, you could use Files.readAllLines (if you're using Java 7).
Path p1 = //Path to file one
Path p2 = //Path to file two
Charset cs = //encoding of the files
List<String> datasFileOne = Files.readAllLines(p1, cs);
List<String> datasFileTwo = Files.readAllLines(p2, cs);
if(datasFileOne.size() == datasFileTwo.size()){
Collections.sort(datasFileOne);
Collections.sort(datasFileTwo);
if(datasFileOne.equals(datasFileTwo)){
//same content
}
} else {
//not same content
}

Extracting data from a collection in Java

I have a csv dataset like this:
A, 10, USA
B,30, UK
C,4,IT
A,20,UK
B,10,USA
I want to read this csv lines and provide the following output:
A has ran 30 miles with average of 15.
B has ran 30 miles with average of 20.
C has ran 4 miles with average of 4.
I want to achieve this in Java. I have done this in C# by using Linq:
var readlines = File.ReadAllLines(filename);
var query = from lines in readlines
let data = lines.Split(',')
select new
{
Name = data[0],
Miles = data[1],
};
var values = query.GroupBy(x => new {x.Name}).Select(group => new { Person = group.Key, Events = group.Sum(g =>Convert.ToDouble(g.Miles)) ,Count = group.Count() });
I am looking to do this in Java, and I am not sure if I can do this without using any third party library or not? Any ideas?
So far, my code looks like this in Java:
CSVReader reader = new CSVReader(new FileReader(filename));
java.util.List<String[]> content = reader.readAll();
String[] row = null;
for(Object object:content)
{
row = (String[]) object;
String Name = row[0];
String Miles = row[1];
System.out.printf("%s has ran %s miles %n",Name,Miles);
}
reader.close();
}
I am looking for a nice way to get the total milage value for each name to calculate for the average.
As a C# developer, it is hard sometimes not to miss the features of linq. But as Farlan suggested you could do something like this:
CSVReader reader = new CSVReader(new FileReader(filename));
java.util.List<String[]> content = reader.readAll();
Map<String, Group> groups = new HashMap<>();
for(String[] row : content)
{
String Name = row[0];
String Miles = row[1];
System.out.printf("%s has ran %s miles %n", Name, Miles);
if (groups.containsKey(Name)){
groups.get(Name).Add(Double.valueOf(Miles));
} else {
Group g = new Group();
g.Add(Double.valueOf(Miles));
groups.put(Name, g);
}
}
reader.close();
for (String name : groups.keySet())
{
System.out.println(name + " ran " + groups.get(name).total() + " with avg of " + groups.get(name).average());
}
}
class Group {
private List<Double> miles;
public Group()
{
miles = new ArrayList<>();
}
public Double total(){
double sum = 0;
for (Double mile : miles)
{
sum += mile;
}
return sum;
}
public Double average(){
if (miles.size() == 0)
return 0d;
return total() / miles.size();
}
public void Add(Double m){
miles.add(m);
}
}
Use Java's BufferedReader class:
BufferedReader in = new BufferedReader(new FileReader("your.csv"));
String line;
while ( (line = in.readLine()) != null) {
String [] fields = line.split(",");
System.out.println(fields[0] + " has ran " + fields[1] + " miles with average " + fields[2]);
}
There are quite a few ways to do this, some long-winded approaches, some shorter. The issue is that Java can be very verbose for doing simple tasks, so the better approaches can be a bit uglier.
The example below shows you exactly how to achieve this, par the printing. Bear in mind however, it might not be the best approach but I feel its more of the easier ones to read and comprehend.
final File csvFile = new File("filename.csv");
final Scanner reader = new Scanner(csvFile);
final Map<String, Integer> info = new HashMap<>(); //Store the data
//Until there is are no more lines, continue
while (reader.hasNextLine()) {
final String[] data = reader.nextLine().split(","); // data[0] = A. [1] = 10. [2] = USA
final String alpha = data[0];
if (!info.containsKey(alpha)) {
info.put(alpha, Integer.parseInt(data[1]));
} else {
int miles = info.get(alpha);
info.put(alpha, miles + Integer.parseInt(data[1]));
}
}
reader.close();
The steps involved are simple:
Step 1 - Read the file.
By passing a File into the Scanner object, you set the target parsing to the File and not the console. Using the very neat hasNextLine() method, you can continually read each line until no more exist. Each line is then split by a comma, and stored in a String array for reference.
Step 2 - Associating the data.
As you want to cumulatively add the integers together, you need a way to associate already passed in letters with the numbers. A heavyweight but clean way of doing this is to use a HashMap. The Key which it takes is going to be a String, specifically A B or C. By taking advantage of the fact the Key is unique, we can use the O(1) containsKey(String) method to check if we've already read in the letter. If its new, add it to the HashMap and save the number with it. If however, the letter has been seen before, we find the old value, add it with the new one and overwrite the data inside the HashMap.
All you need to do now is print out the data. Feel free to take a different approach, but I hope this is a clear example of how you CAN do it in Java.
Maybe you could try this Java library: https://code.google.com/p/qood/
It handles data without any getter/setters, so it's more flexible than LINQ.
in your case, file "D:/input.csv" has 3 columns:
NAME,MILES,COUNTRY
A, 10, USA
B,30, UK
C,4,IT
A,20,UK
B,10,USA
the query code would be:
final QModel raw = QNew.modelCSV("D:/input.csv")
.debug(-1);//print out what read from CSV
raw.query()
.selectAs("OUTPUT",
"CONCAT(NAME,' has ran ',SUM(MILES),' miles with average of ',MEAN(MILES),'.')")
.groupBy("NAME")
.result().debug(-1)//print out the result
.to().fileCSV("D:/output.csv", "UTF-8");//write to another CSV file

Categories

Resources