Java sort lines from text file - java

I need to read players from text file, and then output top 3, 5 or 10 players depends on users choice.
Format of data in text file is:
Name, date, correct answerws, points
John, 21.8.2016, 4/5, 80
Edy, 21.8.2016, 5/5, 100
I need to sort them by points and then output best 3,5 or 10 players as i already write.
Here is what i done so far:
public static void topPlayers(){
File f=new File("results.txt");
Scanner scf=new Scanner(f);
Scanner sc=new Scanner(System.in);
Scanner sc2=new Scanner(f);
while(sc2.hasNextLine()){
String p1=scf.nextLine();
String[] niz=p1.split(", ");
}
sc2.close();
System.out.println("Choose an option: ");
System.out.println("1. Top 3 players");
System.out.println("2. Top 5 players");
System.out.println("3. Top 10 players");
int op=sc.nextInt();
if(op==1){
System.out.println("Top 3 players: ");
for(int i=0; i<3; i++){
//System.out.println(....);
}
}
else if(op==2){
System.out.println("Top 5 players: ");
for(int i=0; i<5; i++){
//System.out.println(....);
}
}
else if(op==3){
System.out.println("Top 10 players: ");
for(int i=0; i<10; i++){
//System.out.println(....);
}
}
else{
System.out.println("Wrong option!");
}
}
How to sort this lines from text file by players point?

I highly recommend that you approach this using BufferedReader rather than having three scanners. This snippet will cause you infinite headaches:
File f=new File("results.txt");
Scanner scf=new Scanner(f);
Scanner sc=new Scanner(System.in);
Scanner sc2=new Scanner(f);
Instead, use something resembling this:
File f = new File("results.txt");
FileReader fileIn = new FileReader(f);
BufferedReader reader = new BufferedReader(fileIn);
Using this approach, you can read line by line or segment by segment using ", " and "\n" as delimeters or whatever else you need.

Use the array niz to recreate instances of the player class..
(yes, you will need if not already, to create a player class)
then from every line create a player and add it to a java.util.list
ther sort them with a given criteria... correctAnswers or totalPoints
up to your needs.
Example:
List<Player> myPlayers = new ArrayList<>();
while(sc2.hasNextLine()){
String p1=scf.nextLine();
String[] niz=p1.split(", ");
myPlayers.add(new Player(niz));
}
Collections.sort(myPlayers, new Comparator<Player>() {
#Override
public int compare(Player o1, Player o2) {
return Integer.compare(o1.getTotalPoints(), o2.getTotalPoints());
}
});
after this, a sublist can give you the players you need
i.e
myPlayers.subList(0, 2);
will give the 1st 3 players...
where foo is an instance or an anonymous comparator implementor...

How about old good Stream API?
Customize sortingKeyIndex, separator, neededLines to fit special needs.
import java.nio.file.*;
import java.util.Comparator;
import java.util.stream.Stream;
public class FileSortWithStreams {
public static void main(String[] args) throws Exception {
Path initialFile = Paths.get("files/initial.txt");
Path sortedFile = Paths.get("files/sorted.txt");
int sortingKeyIndex = 3;
String separator = ", ";
int neededLines = 5;
Comparator<String[]> reversedPointsComparator =
Comparator
.<String[], Integer>comparing(s -> extractAsInt(s, sortingKeyIndex))
.reversed();
Stream<CharSequence> sortedLines =
Files.lines(initialFile)
.map(s -> s.split(separator))
.sorted(reversedPointsComparator)
.limit(neededLines)
.map(s -> String.join(separator, s));
Files.write(sortedFile, sortedLines::iterator, StandardOpenOption.CREATE);
}
static int extractAsInt(String[] items, int index) {
return Integer.parseInt(items[index]);
}
}

Related

How to run while loop till user enter input?

I am trying to run while loop for each input user enter but don't know how to stop if user is not entering input.
I need help in stopping while loop if user doesn't enter input.
Code:
import java.util.*;
class petrol{
public static void main(String[] args){
int vehicle_counter=0,petrol_counter=0;
System.out.println("Enter quantity of petrol to be filled in vehicles seperated by space:");
Scanner s1 = new Scanner(System.in);
ArrayList<Integer> array = new ArrayList<Integer>();
while(true){
if(petrol_counter<=200 && array.size()<50){
int input = s1.nextInt();
petrol_counter=petrol_counter+input;
vehicle_counter++;
array.add(input);
}
else{
System.out.println("Quantity Excedded then 200 Litres or no of Vehicles excedded then 50.");
break;
}
}
System.out.println("Hii");
}
}
e.g: If I enter 2 3 4 2 and press enter loop should stop.
Problem with possible solution :
If I use while(s1.nextInt().equals(true)) I get an error.
How do I use break?
So, you can try something like this. Instead of Scanner, use BufferedReader to parse the input since all you need is a single line input. Also, BufferedReader is faster compared to Scanner.
Here is the code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Petrol {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int vehicle_counter=0,petrol_counter=0;
System.out.println("Enter quantity of petrol to be filled in vehicles seperated by space:");
String input = br.readLine();
String[] values = input.split(" ");
if(values.length>50){
System.out.println("Vehicles exceeded 50");
}else{
for(int i=0;i<values.length;i++){
int ip = Integer.parseInt(values[i]);
petrol_counter+=ip;
vehicle_counter++;
if(petrol_counter>200){
System.out.println("Petrol Quantity exceeded 200L");
}
}
}
System.out.println(petrol_counter+" Litres "+ " Vehicles "+vehicle_counter);
}
}
If you want to keep the Scanner you could also make the input as char and having a if statement that will exit the loop when you press a certain character.
import java.util.*;
public class petrol {
public static void main(String[] args) {
int vehicle_counter = 0, petrol_counter = 0;
System.out.println("Enter quantity of petrol to be filled in vehicles seperated by space:");
Scanner s1 = new Scanner(System.in);
ArrayList<Integer> array = new ArrayList<Integer>();
while (true) {
if (petrol_counter <= 200 && array.size() < 50) {
char input = s1.next().charAt(0); // use char instead
if (input == 'q' || input == 'Q') { //if user enters q or Q
System.out.println("Quantity Excedded then 200 Litres or no of Vehicles excedded then 50.");
break;
}
petrol_counter = petrol_counter + input;
vehicle_counter++;
array.add((int) input); //Cast to int
}
}
System.out.println("Hii");
}
}

Java - error when creating arraylist

So I am a beginner to java (not to programming), and I encoutered a problem where it wont let me create an arrayList:
import java.io.*;
import java.util.ArrayList;
import java.util.*;
public class OrderingNumbers{
public static void main (String[] args)throws IOException{
boolean keepRunning = true;
List<String> numbers = new ArrayList<String>(); //<--this one does not work
ArrayList sortedNumbers = new ArrayList();//<-- This one works
while(keepRunning){
DataInputStream input = new DataInputStream(System.in);
System.out.print("Do you want to sort the numbers or add a number?");
String answer = input.readLine();
if(answer.equals("sort")){
for(int i = 0; i < numbers.size(); i++){
System.out.println(numbers.get(i));
}
System.out.println("Bye Bye.");
keepRunning = false;
}else if(answer.equals("add")){
System.out.print("What number to you want to add?");
numbers.add(input.readLine());
System.out.println("Added number.");
}else{
System.out.print("That is not an option.");
}
}
}
}
I have tried doing this as well, ArrayList<String> strArrayList = new ArrayList<String>(); but still does not work. I am trying to allow the user to add another number to the array if they want.
import java.io.*;
import java.util.*;
public class OrderingNumbers{
public static void main (String[] args)throws IOException{
boolean keepRunning = true;
// here is the corrected line
List numbers = new ArrayList();
ArrayList sortedNumbers = new ArrayList();//<-- This one works
// add data to sort
numbers.add(0, 1); // adds 1 at 0 index
numbers.add(1, 2); // adds 2 at 1 index
System.out.println(numbers);
while(keepRunning){
Scanner input = new Scanner(System.in);
System.out.print("Do you want to sort the numbers or add a number?");
String answer = input.nextLine();
if(answer.equalsIgnoreCase("sort")){
for(int i = 0; i < numbers.size(); i++){
System.out.println(numbers.get(i));
// note does not actually do any sorting
}
System.out.println("Bye Bye.");
keepRunning = false;
}else if(answer.equalsIgnoreCase("add")){
System.out.print("What number to you want to add?");
numbers.add(input.nextLine());
System.out.println("Added number.");
}else{
System.out.print("That is not an option.");
}
}
}
}
The normal usage is as follows:
import java.util.List;
List<String> numbers = new ArrayList<>();
List<String> sortedNumbers = new ArrayList<>();
So typically:
Most general type (List) for variables so implementation may be changed later, and all kind of Lists will fit.
Always typed List<...>.
Using the diamond <> operator.
The error might have been an import java.awt.List; which is an other class with the same name. Probably not here.
To sort (integer) numbers a List<Integer> would seem more logic, as 9 < 10, but "9" greater than "10" alphabetically.
For reading text better use Scanner as mentioned in an other answer. It has:
if (scanner.hasNextInt()) {
int number = scanner.nextInt();
numbers.add(number); // adds an Integer with number's value.
...
The real error is unclear however.

Student Array menu

I'm coding a menu to store names into an array, then giving options to add/delete students and search for a particular student as well, but I cant seem to find out how to set the array so that I can use it in other options, cause, for example, my code only allows me to input names when I use option 1, but it doesnt keep these names in the array when I choose option 3 to search for a name within the array, it just shows up as null for every slot in the array.
Another problem I am having is about how I can delete students, obviously it would be really easy if the name is at the end of the array but what if the name is in the middle, how would I be able to delete the name, shift all the other names down one slot so that there are no gaps in the array?
import java.util.Scanner;
public class Lab10Ex2 {
public static void main(String[] args) {
int choice = 0;
int[] stringArray = {};
do{
String[] stringarray = new String[20];
System.out.println("----------------MENU---------------");
System.out.println();
System.out.println("1. Add Students");
System.out.println("2. Delete Students");
System.out.println("3. Search for student");
System.out.println("4. Print all Students");
System.out.println("5. exit");
Scanner scanchoice = new Scanner(System.in);
choice = scanchoice.nextInt();
if (choice ==1){
Scanner scannames = new Scanner(System.in);
System.out.println("Please enter the student names into the array");
int i = 0;
for(i = 0; i<stringarray.length; i++){
String temp =scannames.nextLine();
stringarray[i]=temp.toLowerCase();
if(i==(stringarray.length-1)){
System.out.println("successfully filled up array fully");
System.out.println();
}
}
}
if(choice==2){
}
if(choice==3){
for(int p = 0; p<stringarray.length; p++){
System.out.println(stringarray[p]);
}
int x=0;
Scanner scannames1 = new Scanner(System.in);
System.out.println("Enter name of student you want to search for: ");
System.out.println();
String search=scannames1.nextLine();
String searchName=search.toLowerCase();
for(int p=0;p<20;p++){
if(searchName.equals(stringarray[p])){
x=1;
}
else{
x=0;
}
}
if(x==1){
System.out.println("We have a match in our database for "+ searchName);
}
else if (x==0){
System.out.println("No match for "+ searchName);
}
}
if (choice ==4){
System.out.println("List of names:");
for(int p = 0; p<stringarray.length; p++){
System.out.println(stringarray[p]);
}
}
}while(choice!=5);
}
}
int choice = 0;
int[] stringArray = {};
do{
String[] stringarray = new String[20];
Delete the int[] stringArray line (you don't refer to it anywhere).
Move the String[] stringarray up, outside the loop.
As to deleting, you either have to code that yourself (move everything past the deleted item up one in the array), or use one of the collection classes provided with Java (instead of a native array), which handle deletion for you.
do{
String[] stringarray = new String[20];
On each iteration of your Do { ... } loop, you're recreating the stringarray variable, thus clearing it. If you move this outside of the loop, your student entries will be maintained.
As for deleting, if you're not required to use an array of strings, I would recommend using an ArrayList. It will allow you to easily remove specific entries without worrying about the other entries. Otherwise, yes, the simplest thing to do would be to move all of the other entries down one slot to avoid gaps
Here is the corrected code:
import java.util.Scanner;
public class Lab10Ex2 {
/**
* #param args
*/
public static void main(String[] args) {
int choice = 0;
int[] stringArray = {};
String[] stringarray = new String[20];
do{
System.out.println("----------------MENU---------------");
System.out.println();
System.out.println("1. Add Students");
System.out.println("2. Delete Students");
System.out.println("3. Search for student");
System.out.println("4. Print all Students");
System.out.println("5. exit");
Scanner scanchoice = new Scanner(System.in);
choice = scanchoice.nextInt();
if (choice ==1){
Scanner scannames = new Scanner(System.in);
System.out.println("Please enter the student names into the array");
System.out.println();
int i = 0;
for(i = 0; i<stringarray.length; i++){
String temp =scannames.nextLine();
stringarray[i]=temp.toLowerCase();
if(i==(stringarray.length-1)){
System.out.println("successfully filled up array fully");
System.out.println();
}
}
}
if(choice==2){
}
if(choice==3){
for(int p = 0; p<stringarray.length; p++){
System.out.println(stringarray[p]);
}
int x=0;
Scanner scannames1 = new Scanner(System.in);
System.out.println("Enter name of student you want to search for: ");
System.out.println();
String search=scannames1.nextLine();
String searchName=search.toLowerCase();
for(int p = 0; p < stringarray.length ;p++){
if(searchName.equals(stringarray[p])){
x=1;
break;
}
else{
x=0;
}
}
if(x==1){
System.out.println("We have a match in our database for "+ searchName);
}
else if (x==0){
System.out.println("No match for "+ searchName);
}
}
if (choice ==4){
System.out.println("List of names:");
for(int p = 0; p<stringarray.length; p++){
System.out.println(stringarray[p]);
System.out.println();
}
}
}while(choice!=5);
}
}
Things you were doing wrong:
Instantiating the array in the do while loop.
Not breaking out of the loop if a search entity was found in the array.
Use ArrayList if you want to avoid wasting space in arrays after deletion. If you are bound to this with simple arrays, you can do this:
Place null at index from which you deleted.Create a temporary array with same size as the original one with all null values. Copy all the elements from the original array to the temporary one but skip elements that are null. Point the original array to the new array.
AND AVOID HARD CODING ARRAY LENGTHS!

Cannot Store Data into ArrayLists?

thanks for all the help guys but now the nature of the question has changed using Patrick's suggestion below loop is running but it dise not seem to be storing the input to respective arrays data keeps hetting replaced into the ArrayLists rather than going to the next position into the ArrayList any suggestions?
import java.util.ArrayList;
import java.util.Scanner;
public class Arrray {
public static void main(String [] args){
ArrayList<String> names;
ArrayList<String> addr;
do {
names = new ArrayList<String>();
addr = new ArrayList<String>();
Scanner userInput = new Scanner(System.in);
System.out.println("Name and Adreess are: " + names.size() + "**"
+ addr.size());
System.out.println("please Enter Your Name :");
names.add(userInput.next());
System.out.println("please enter your Address :");
addr.add(userInput.next());
System.out.println("Do you want to add another entry? :(y/n)" );
String ans =userInput.next(); // get the value from the user using scanner class
if(ans.equals("n") || ans.equals("N"))
break;
} while (true);
int n = names.size();
int a = addr.size();
for(int i =0; i<n && i<a; i++ )
System.out.println("Name and address are as below: "+ names.get(i)+"**"+ addr.get(i));
}
}
Use a while(true) in conjunction with a break statement:
do {
if(input.next() == 'n'){
break;
}
} while(true);
get value from the user and if user enter n then break otherwise nothing
System.out.println("Do you want to add another entry? :(y/n)" );
String ans = .... // get the value from the user using scanner class
if(ans.equalsIgnoreCase("n"))
break;
Try to capture this user's input
System.out.println("Do you want to add another entry? :(y/n)");
and use that info in the while.
You have to do something like this:
String choice = "";
do {
.
.
.
.
System.out.println("Do you want to add another entry? :(y/n)" );
choice = userInput.next();
} while (!(choice.equals("n") || choice.equals("N")));
The line
choice = userInput.next();
will read user input, and the String classes equals method for comparing the input. The loop will continue until the choice is either N or n.
import java.util.ArrayList;
import java.util.Scanner;
public class Array {
public static void main(String[] args) {
ArrayList<String> name = new ArrayList<String>();
ArrayList<Integer> phone = new ArrayList<Integer>();
Scanner scanner = new Scanner(System.in);
String answer = "";
do {
System.out.println("Please enter your name: ");
name.add(scanner.next());
System.out.println("Please enter your number: ");
phone.add(scanner.nextInt());
System.out.println("Do you want to add a directory y/n?");
answer = scanner.next();
} while (answer.equals("y") || answer.equals("Y"));
if (answer.equals("y") || answer.equals("Y")); //want it to go back to start another direcotry here
else {
System.out.println("Thanks for adding to the directory");
for (int i = 0; i < name.size(); i++) {
System.out.print(name.get(i) + "\t");
System.out.print(phone.get(i));
System.out.println("");
}
}
}
}

Storing Inputs in Two Related Arrays

I am working in a small task that allow the user to enter the regions of any country and store them in one array. Also, each time he enters a region, the system will ask him to enter the neighbours of that entered region and store these regions.
My idea is each time the user enters the region, the system will store it in an arrya and each time he enters a region, the system will ask him to enter the neighbours of that region before he enters the second region and so on, and store these inputs in a second array under a pointer of the related entry in the first array.
what I did is just the beginning as follow:
import java.util.Arrays;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner kb = new Scanner(System.in);
String [] regionArray = new String[5];
for (int i = 0; i < regionArray.length; i++) {
System.out.print("Please enter the region: ");
regionArray[i] = kb.next();
//kb.nextLine(); // to get and discard the nextline token
}
System.out.print("You have entered: ");
System.out.println(Arrays.toString(regionArray));
}
}
For example, assume we have 4 regions: a, b, c, d, and a has two neighbours: b and d. In this case when the user enters the first region which is (a), he will be asked to enter its neighbours which are b and d, then he will be able to enter the second region which is b and so on.
the problem now, How can I genereated the second array and make it linked to the first array?
Please help me
Thank you for your help. I really appreciate it.
Now I have used the Hashmap and everything is working well but I faced another problem in the retrieving specific region or neighbour. Besides that, I need to retrieve each one of them separatley in order to be able to apply four-colour theorem to each one of them, So how can I do that?
My Code was as following:
import java.util.*;
import java.util.HashMap;
public class Test5{
public static void main(String[]args){
HashMap<String, String> neighbour = new HashMap<String, String>();
Scanner kb = new Scanner(System.in);
for(;{
System.out.println ("Enter the neighbours first then the region... and when finished press q");
String n = kb.nextLine();
if (n.equalsIgnoreCase("Q"))
break;
System.out.print("region: ");
String region = kb.nextLine();
neighbour.put(region, n);
}
System.out.println(neighbour);
}
}
I suggest you use collections such as Map<String, Set<String>> where the key is the region and the Set contains the neighboring regions. I would also maintain a Set of the regions whose neighbours haven't been entered. Note: is 'a' neighbours 'b' it should also be the other way around.
I used the arrays, but unfortunately there is only one missed thing which is the size of neighbours array will be fixed for each region and this is will not be appropriate even in our real life.
For instance, if region A has two neighbours, that is not necessary that other regions have the same number of neighbours. So in this case what should I do?
Besides that, I have error in compiling my code, after entering the neighbours for the first region.
And this is my code:
import java.io.*;
import java.util.Scanner;
public class Test4 {
public static void main(String[] args) {
System.out.println("Please enter the number of neighbours");
Scanner kb = new Scanner(System.in);
BufferedReader reader = new BufferedReader(
new InputStreamReader(System.in));
try {
int size = Integer.parseInt(reader.readLine());
//SIZE is size of the neighbours array
String[][] regions = new String[5][size];
for (int i = 0; i < 5; i++) {
System.out.println("Please enter the region #"
+ (i + 1) + ": ");
String input = reader.readLine();
regions[i][0] = input; //get input for region;
for (int j = 1; j <= size; j++) {
System.out.println("Please enter the neighbour #"
+ (j) + ": ");
String n = reader.readLine();
regions[i][j] = n; //get input for neighbours
}
}
} catch (IOException ioe) {
System.out.println("An error have occured");
}
}
}
For instance, if region A has two neighbours, that is not necessary that other regions have the same number of neighbours. So in this case what should I do?
I'd recommend one of the proposed Collection solutions, but the goal may be to understand multi-dimensional arrays. You can have a different size for each neighbor array, but you'll have to determine the size for each row inside the outer loop, as suggested below.
import java.util.Arrays;
import java.util.Scanner;
public class Test5 {
private static final int REGION_COUNT = 2;
public static void main(String[] args) {
System.out.println("Please enter the number of neighbours; "
+ "enter 'q' to quit.");
Scanner kb = new Scanner(System.in);
String[][] regions = new String[REGION_COUNT][];
for (int r = 0; r < regions.length; r++) {
System.out.print("How many heighbors for region #"
+ (r + 1) + ": ");
if (kb.hasNextInt()) {
int size = kb.nextInt();
regions[r] = new String[size];
kb.nextLine();
for (int n = 0; n < size; n++) {
System.out.print("Please enter the neighbour #"
+ (n) + ": ");
regions[r][n] = kb.nextLine();
}
} else System.exit(0);
}
for (String[] neighbors : regions) {
System.out.println(Arrays.toString(neighbors));
}
}
}
You can create a class or structure with a region and an array of its neighbouring regions.So that you can access both the region easily.
Cheers,
Dwarak
This would be much easier using a combination of a Map and a Collection such as a Set:
Map<String, Set<String>> map = new HashMap<String, Set<String>>();
map.put("some region", new HashSet<String>());
map.get("some region").add("some neighbor");
map.get("some region").add("some other neighbor)";
System.out.println("some region's neighbors:");
for(String neighbor : map.get("some region")) {
System.out.println(neighbor);
}

Categories