Extracting data from a collection in Java - 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

Related

Parsing input from file, delimiters, loops, java

The overall project is creating a system manager for airports. It keeps track of airports, flights, seating sections, seats and other relevent info for each of those catagories. The initial system is set up by importing from a file that's formatted a certain way. I'm having problems parsing the file properly to set up the initial system. the data is parsed from the file and used as method parameters to create the objects: Airport, Airline, Flight, FlightSection, and Seat.
the formatting is:
[list-of-airport-codes] {list-of-airlines}
list-of-airport-codes ::= comma-separated strings
list-of-airlines ::= airline-name1[flightinfo-list1], airline-name2[flightinfo-list2], airlinename3[flightinfo-list3], …
flightinfo-list ::= flightID1|flightdate1|originAirportCode1|destinationAirportCode1[flightsectionlist1], flightID2|flightdate2|originAirportCode2|destinationAirportCode2[flightsection-list2], …
flightdate ::= year, month, day-of-month, hours, minutes
flightsection-list ::= sectionclass: seat-price: layout: number-of-rows, …
sectionclass ::= F, B, E (for first class, business class, economy class)
layout ::= S, M, W (different known seating layouts)
example:
[DEN,NYC,SEA,LAX]{AMER[AA1|2018,10,8,16,30|DEN|LAX[E:200:S:4,F:500:S:2],
AA2|2018,8,9,7,30|LAX|DEN[E:200:S:5,F:500:S:3], …], UNTD[UA21|2018,11,8,12,30|NYC|SEA[E:300:S:6,F:800:S:3], UA12|2018,8,9,7,30|SEA|DEN[B:700:S:5, F:1200:S:2], …], FRONT[…], USAIR[…]}
I tried brute forcing it using a combination of delimiters and while loops. The code successfully creates the Airports, first Airline and Flighsections, but when it gets to creating the second airline it crashes, because i'm not looping properly, and having a hard time getting it right. My code for it as of now, is a mess, and if you're willing to look at it, I would appreciate any constructive input. My question is what would be a better way to approach this? A different design approach? Maybe a smarter way to use the delimiters?
Thanks in advance for your help!!
here's what i've tried.
private void readFile(File file){
System.out.println("reading file");
Scanner tempScan;
String result;
String temp = "";
scan.useDelimiter("\\[|\\{");
try{
// AIRPORTS
result = scan.next();
tempScan = new Scanner(result);
tempScan.useDelimiter(",|\\]");
while(tempScan.hasNext()){
temp = tempScan.next();
sysMan.createAirport(temp);
}
tempScan.close();
/* AIRLINE
* FLIGHT
* FLIGHTSECTION
*/
do{
// AIRLINE (loop<flight & fsection>)
result = scan.next();
sysMan.createAirline(result);
// FLIGHT
result = scan.next();
tempScan = new Scanner(result);
do{
tempScan.useDelimiter(",|\\|");
ArrayList flightInfo = new ArrayList();
while(tempScan.hasNext()){
if(tempScan.hasNextInt()){
flightInfo.add(tempScan.nextInt());
} else {
flightInfo.add(tempScan.next());
}
}
tempScan.close();
sysMan.createFlight(sysMan.getLastAddedAirline(),(String)flightInfo.get(0), (int)flightInfo.get(1), (int)flightInfo.get(2), (int)flightInfo.get(3), (int)flightInfo.get(4), (int)flightInfo.get(5), (String)flightInfo.get(6), (String)flightInfo.get(7));
// FLIGHTSECTION (loop<itself>)
result = scan.next();
tempScan = new Scanner(result);
tempScan.useDelimiter(",|:|\\]");
ArrayList sectInfo = new ArrayList();
int i = 1;
while(!temp.contains("|")){
if(tempScan.hasNextInt()){
sectInfo.add(tempScan.nextInt());
} else {
temp = tempScan.next();
if(temp.equals(""))
break;
char c = temp.charAt(0);
sectInfo.add(c);
}
if(i == 4){
sysMan.createSection(sysMan.getLastAddedAirline(), sysMan.getLastAddedFlightID(), (char)sectInfo.get(0), (int)sectInfo.get(1), (char)sectInfo.get(2), (int)sectInfo.get(3));
i = 1;
sectInfo = null;
sectInfo = new ArrayList();
continue;
}
i++;
}
}while(!temp.equals("\\s+"));
}while(!temp.contains("\\s+"));
}catch(NullPointerException e){
System.err.println(e);
}
}
I'd rather chunk it down by regexp mathing the outer bounds, have a look, I took it a couple of levels broken.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Tokeni {
static String yolo = "[DEN,NYC,SEA,LAX]{AMER["
+ "AA1|2018,10,8,16,30|DEN|LAX[E:200:S:4,F:500:S:2],"
+ "AA2|2018,8,9,7,30|LAX|DEN[E:200:S:5,F:500:S:3]],"
+ "UNTD[UA21|2018,11,8,12,30|NYC|SEA[E:300:S:6,F:800:S:3],"
+ "UA12|2018,8,9,7,30|SEA|DEN[B:700:S:5, F:1200:S:2]]}";
public static void main(String[] args) {
Matcher airportCodesMatcher = Pattern.compile("\\[(.*?)\\]").matcher(yolo);
airportCodesMatcher.find();
String[] airportCodes = airportCodesMatcher.group(1).split(",");
Matcher airLinesMatcher = Pattern.compile("\\{(.*?)\\}").matcher(yolo);
airLinesMatcher.find();
String airLinesStr = airLinesMatcher.group(1);
System.out.println(airLinesStr);
Pattern airLinePattern = Pattern.compile("\\D+\\[(.*?)\\]\\]");
Matcher airLineMatcher = airLinePattern.matcher(airLinesStr);
while( airLineMatcher.find() ) {
String airLineStr = airLineMatcher.group(0).trim();
if(airLineStr.startsWith(",")) {
airLineStr = airLineStr.substring(1, airLineStr.length()).trim();
}
System.out.println(airLineStr);
Matcher airLineNameMatcher = Pattern.compile("[A-Z]+").matcher(airLineStr);
airLineNameMatcher.find();
String airLineName = airLineNameMatcher.group(0).trim();
System.out.println(airLineName);
airLineStr = airLineStr.substring(airLineStr.indexOf("[")+1, airLineStr.length());
Matcher airLineInfoMatcher = Pattern.compile("\\D+(.*?)\\]").matcher(airLineStr);
while(airLineInfoMatcher.find()) {
String airLineInfoStr = airLineInfoMatcher.group(0).trim();
if(airLineInfoStr.startsWith(",")) {
airLineInfoStr = airLineInfoStr.substring(1, airLineInfoStr.length()).trim();
}
System.out.println(airLineInfoStr);
}
}
}
}

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

Java.Lang.Double[] to Double[] issue for Polynomial from CSV

First of all thanks for your help in advance.
I'm writing an investment algorithm and am currently pre-processing CSV historical data. The end goal for this part of the process is to create a symmetrical co-variance matrix of 2k x 2k / 2 (2 million) entries.
The Java class I'm writing takes a folder of CSVs each with 8 bits of information, key ones being Date, Time & Opening stock price. Date & time have been combined into one 'seconds from delta' time measure and opening stock prices remain unchanged. The output CSV contains the above two pieces of information also with a filename index for later referencing.
In order to create the co-variance matrix each stock on the NYSE must have a price value for every time, if values are missing the matrix cannot be properly completed. Due to discrepancies between time entries in the historical training CSV, I have to use a polynomial function to estimate missed values, which then can be fed into the next process in the chain.
My problem sounds fairly simple and should be easy to overcome (I'm probably being a massive idiot). The polynomial package I'm using takes in two arrays of doubles (Double[] x, Double[] y). X pertaining to an array of the 'seconds past delta' time values of a particular stock and Y the corresponding price. When I try to feed these in I'm getting a type error as what I'm actually trying to input are 'java.lang.Double' objects. Can anyone help me with converting an array of the latter to an array of the former?
I realise there is a load of ridiculousness after the main print statement, these are just me tinkering trying to miraculously change the type.
Again thanks for your time, I look forward to your replies!
Please find the relevant method below:
public void main(String filePath) throws IOException {
String index = filePath;
index = index.replace("/Users/louislimon/Desktop/Invest Algorithm/Data/Samples US Stock Data/data-1/5 min/us/nyse stocks/1/", "");
index = index.replace(".us.txt", "");
File fout = new File("/Users/louislimon/Desktop/Invest Algorithm/Data.csv");
FileOutputStream fos = new FileOutputStream(fout);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
Reader in = new FileReader(filePath);
Iterable<CSVRecord> records;
try {
records = CSVFormat.EXCEL.withSkipHeaderRecord(true).parse(in);
} catch ( IOException ex ) {
System.out.println ( "[ERROR] " + ex );
return;
}
ZoneId zoneId = ZoneId.of("America/New_York");
boolean tmp = true;
Instant firstInstant = null; // Track the baseline against which we calculate the increasing time
ArrayList<Double> timeVals = new ArrayList<Double>();
ArrayList<Double> priceVals = new ArrayList<Double>();
for ( CSVRecord record : records ) {
if(tmp){
tmp = false;
}
else {
//System.out.println(record.toString());
String dateInput = record.get(0);
String timeInput = record.get(1);
Double price = Double.parseDouble(record.get(2));
LocalDate date = LocalDate.parse(dateInput);
LocalTime time = LocalTime.parse(timeInput);
//Double price = Double.parseDouble(priceInput);
LocalDateTime ldt = LocalDateTime.of(date, time);
ZonedDateTime zdt = ldt.atZone(zoneId);
Instant instant = zdt.toInstant(); // Use Instant (moment on the timeline in UTC) for data storage, exchange, serialization, database, etc.
if (null == firstInstant) {
firstInstant = instant; // Capture the first instant.
}
Duration duration = Duration.between(firstInstant, instant);
Long deltaInSeconds = duration.getSeconds();
double doubleDeltaInSeconds = deltaInSeconds.doubleValue();
timeVals.add(doubleDeltaInSeconds);
priceVals.add(price);
//System.out.println("deltaInSeconds: " + deltaInSeconds + " | price: " + price + " | index: " + index);
}
Double [] timeValsArray = timeVals.toArray(new Double[timeVals.size()]);
Double [] priceValsArray = timeVals.toArray(new Double[priceVals.size()]);
Double[] timeFeed = new Double[timeVals.size()];
Double[] priceFeed = new Double[priceVals.size()];
for(int x = 0;x<timeVals.size(); x++) {
timeFeed[x] = new Double (timeValsArray[x].doubleValue());
priceFeed[x] = new Double (priceValsArray[x]);
}
PolynomialFunctionLagrangeForm pflf = new PolynomialFunctionLagrangeForm(timeFeed,priceFeed);
}
According to the documentation, the PolynomialFunctionLagrangeForm constructor takes two double[] arrays, not Double[].
Hence you need to create a raw array and pass that:
...
double[] timeFeed = new double[timeVals.size()];
double[] priceFeed = new double[priceVals.size()];
for(int x = 0; x < timeVals.size(); x++) {
timeFeed[x] = timeValsArray[x].doubleValue();
priceFeed[x] = priceValsArray[x].doubleValue();
}
...
See also How to convert an ArrayList containing Integers to primitive int array? for some alternative ways to convert an ArrayList<T> (where T is a wrapper for a primitive type) to the corresponding raw array T[].
Note that there is also obviously a typo in your code:
Double [] priceValsArray = timeVals.toArray(new Double[priceVals.size()]);
needs to be
Double [] priceValsArray = priceVals.toArray(new Double[priceVals.size()]);

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

manipulate and sort text file

I am working on a project where I have been given a text file and I have to add up the points for each team and printout the top 5 teams.
The text file looks like this:
FRAMae Berenice MEITE 455.455<br>
CHNKexin ZHANG 454.584<br>
UKRNatalia POPOVA 453.443<br>
GERNathalie WEINZIERL 452.162<br>
RUSEvgeny PLYUSHCHENKO 191.399<br>
CANPatrick CHAN 189.718<br>
CHNHan YAN 185.527<br>
CHNCheng & Hao 271.018<br>
ITAStefania & Ondrej 270.317<br>
USAMarissa & Simon 264.256<br>
GERMaylin & Daniel 260.825<br>
FRAFlorent AMODIO 179.936<br>
GERPeter LIEBERS 179.615<br>
JPNYuzuru HANYU 197.9810<br>
USAJeremy ABBOTT 165.654<br>
UKRYakov GODOROZHA 160.513<br>
GBRMatthew PARR 157.402<br>
ITAPaul Bonifacio PARKINSON 153.941<br>
RUSTatiana & Maxim 283.7910<br>
CANMeagan & Eric 273.109<br>
FRAVanessa & Morgan 257.454<br>
JPNNarumi & Ryuichi 246.563<br>
JPNCathy & Chris 352.003<br>
UKRSiobhan & Dmitri 349.192<br>
CHNXintong &Xun 347.881<br>
RUSYulia LIPNITSKAYA 472.9010<br>
ITACarolina KOSTNER 470.849<br>
JPNMao ASADA 464.078<br>
UKRJulia & Yuri 246.342<br>
GBRStacey & David 244.701<br>
USAMeryl &Charlie 375.9810<br>
CANTessa & Scott 372.989<br>
RUSEkaterina & Dmitri 370.278<br>
FRANathalie & Fabian 369.157<br>
ITAAnna & Luca 364.926<br>
GERNelli & Alexander 358.045<br>
GBRPenny & Nicholas 352.934<br>
USAAshley WAGNER 463.107<br>
CANKaetlyn OSMOND 462.546<br>
GBRJenna MCCORKELL 450.091<br>
The first three letters represent the team.
the rest of the text is the the competitors name.
The last digit is the score the competitor recived.
Code so far:
import java.util.Arrays;
public class project2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] array = new String[41];
String[] info = new String[41];
String[] stats = new String[41];
String[] team = new String[41];
//.txt file location
FileInput fileIn = new FileInput();
fileIn.openFile("C:\\Users\\O\\Desktop\\turn in\\team.txt");
// txt file to array
int i = 0;
String line = fileIn.readLine();
array[i] = line;
i++;
while (line != null) {
line = fileIn.readLine();
array[i] = line;
i++;
}
//Splitting up Info/team/score into seprate arrays
for (int j = 0; j < 40; j++) {
team[j] = array[j].substring(0, 3).trim();
info[j] = array[j].substring(3, 30).trim();
stats[j] = array[j].substring(36).trim();
}
// Random stuff i have been trying
System.out.println(team[1]);
System.out.println(info[1]);
System.out.println(stats[1]);
MyObject ob = new MyObject();
ob.setText(info[0]);
ob.setNumber(7, 23);
ob.setNumber(3, 456);
System.out.println("Text is " + ob.getText() + " and number 3 is " + ob.getNumber(7));
}
}
I'm pretty much stuck at this point because I am not sure how to add each teams score together.
This looks like homework... First of all you need to examine how you are parsing the strings in the file.
You're saying: the first 3 characters are the country, which looks correct, but then you set the info to the 4th through the 30th characters, which isn't correct. You need to dynamically figure out where that ends and the score begins. There is a space between the "info" and the "stats," knowing that you could use String's indexOf function. (http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#indexOf(int))
Have a look at Maps.
A map is a collection that allows you to get data associated with a key in a very short time.
You can create a Map where the key is a country name, with value being the total points.
example:
Map<String,Integer> totalScore = new HashMap<>();
if (totalScore.containsKey("COUNTRYNAME"))
totalScore.put("COUNTRYNAME", totalScore.get("COUNTRYNAME") + playerScore)
else
totalScore.put("COUNTRYNAME",0)
This will add to the country score if the score exists, otherwise it will create a new totalScore for a country initialized to 0.
Not tested, but should give you some ideas:
public static void main(String... args)
throws Exception {
class Structure implements Comparable<Structure> {
private String team;
private String name;
private Double score;
public Structure(String team, String name, Double score) {
this.team = team;
this.name = name;
this.score = score;
}
public String getTeam() {
return team;
}
public String getName() {
return name;
}
public Double getScore() {
return score;
}
#Override
public int compareTo(Structure o) {
return this.score.compareTo(o.score);
}
}
File file = new File("path to your file");
List<String> lines = Files.readAllLines(Paths.get(file.toURI()), StandardCharsets.UTF_8);
Pattern p = Pattern.compile("(\\d+(?:\\.\\d+))");
List<Structure> structures = new ArrayList<Structure>();
for (String line : lines) {
Matcher m = p.matcher(line);
while (m.find()) {
String number = m.group(1);
String text = line.substring(0, line.indexOf(number) - 1);
double d = Double.parseDouble(number);
String team = text.substring(0, 3);
String name = text.substring(3, text.length());
structures.add(new Structure(team, name, d));
}
}
Collections.sort(structures);
List<Structure> topFive = structures.subList(0, 5);
for (Structure structure : topFive) {
System.out.println("Team: " + structure.getTeam());
System.out.println("Name: " + structure.getName());
System.out.println("Score: " + structure.getScore());
}
}
Just remove <br> from your file.
Loading file into memory
Your string splitting logic looks fine.
Create a class like PlayerData. Create one instance of that class for each row and set all the three fields into that using setters.
Keep adding the PlayerData objects into an array list.
Accumulating
Loop through the arraylist and accumulate the team scores into a hashmap. Create a Map to accumulate the team scores by mapping teamCode to totalScore.
Always store row data in a custom object for each row. String[] for each column is not a good way of holding data in general.
Take a look in File Utils. After that you can extract the content from last space character using String Utils e removing the <br> using it as a key for a TreeMap. Than you can have your itens ordered.
List<String> lines = FileUtils.readLines(yourFile);
Map<String, String> ordered = new TreeMap<>();
for (String s : lines) {
String[] split = s.split(" ");
String name = split[0].trim();
String rate = splt[1].trim().substring(0, key.length - 4);
ordered.put(rate, name);
}
Collection<String> rates = ordered.values(); //names ordered by rate
Of course that you need to adjust the snippet.

Categories

Resources