I have stored two text files into two separate arrays. Now, I am trying to compare both arrays to find duplicate values. I am having issues with my logic, and I am unable to print out the number of times a duplicate value appears.
file1 contains:
1913 2016 1 1913 186
2016 1711 32843 2016 518
3 1913 32843 32001 4
250 5 3500 6 7
8 27 73 9 10
1711 73 11 2 1.4
1.4 12 33.75278 84.38611 1913
19 1930 20 21 1947
22 1955 23 1961 23
1969 27 1995 26 27
1962 28 29 30 1970
31 31
file2 contains:
1913 2016 32843 31 27 1.4 4 7 2 23
I am trying to find values in file2 that are duplicated in file1, and how many times.
I have the following code:
public static void findDuplicates() {
// array for first file
for (int n = 0; n < nums.size(); n++) {
// matches are false by default
boolean match = false;
int count = 0;
String v = nums.get(n);
// array for second file
for (int k = 0; k < nums1.size(); k++) {
String p = nums1.get(k);
// second file contains values from first file
if (p.contains(v)) {
// there is a match
match = true;
// when there is a match print out matched values and the number of times they appear in second file
if (match) {
count++;
System.out.println( p + " " + "is duped" + " " + count + " " + "times");
}
}
}
}
}
When I compile and run this code, this is the output:
31 is duped 1 times
Could someone let me know what I am doing wrong here?
EDIT
Here is the rest of my code:
public static ArrayList<String> nums;
public static ArrayList<String> nums1;
//Create a main method to start the program.
//Add FileNot FoundException in case the file can't be found by computer.
public static void main(String[] args) throws FileNotFoundException{
//The while will help us read the content into our computer piece by piece. It will not stop until the end of assignment.csv.
while(FILE1.hasNext()){
//Create a String variable - TempString. We use TempString to store each piece temporarily.
String TempString = FILE1.next();
String temp1 = TempString.replaceAll("[\\,]", "");
String pattern1 = "[0-9]+\\.{1}[0-9]+";
//Compile the Regular Expression into Pattern and store it in r1 so that the computer can understand the Regular Expression.
Pattern r1 = Pattern.compile(pattern1);
Matcher m1 = r1.matcher(temp1);
String pattern2 = "[0-9]+";
//Compile the Regular Expression into Pattern and store it in r2 so that the computer can understand the Regular Expression.
Pattern r2 = Pattern.compile(pattern2);
Matcher m2 = r2.matcher(temp1);
nums = new ArrayList<String>();
//Recollect, m1 is used to match decimal numbers.
if(!(m1.find())){//if a decimal number CAN'T be found
//We use while statement instead of if statement here.
//If there is only one piece per line, we can use either while statement or if statement.
//However, we have to use while statement if there is more than one piece per line.
while(m2.find()) {//if an integer number CAN be found
//If an Integer is found, we add 1 to Variable count.
count++;
//Even though the number (i.e., m2.group(0)) is an Integer, its data type is String. So we store it to a String variable - number.
String number = m2.group(0);
nums.add(number);
//If the remainder of count by 5 is zero, we display the number and advance to a new line.
if (count % 5 == 0){
System.out.println(number);
}
//Otherwise, we just display the number on the same line and divide numbers by a space.
else
System.out.print(number + " ");
}
}
//If we find a decimal number
else{
//We add 1 to Variable count.
count++;
//Even though the number (i.e., m1.group(0)) is a decimal number, its data type is String. So we store it to a String variable - number.
String number = m1.group(0);
nums.add(number);
//If the remainder of count by 5 is zero, we display the number and advance to a new line.
if (count % 5 == 0) {
System.out.println(number);
}
//Otherwise, we just display the number on the same line and divide numbers by a space.
else
System.out.print(number + " ");
}
}
FILE1.close();//Once we finish the task, we close the file.
while(FILE2.hasNext()){
//Create a String variable - TempString. We use TempString to store each piece temporarily.
String TempString = FILE2.next();
//So I use replaceAll function to eliminate comma (,) and store the new string in temp1.
String temp1 = TempString.replaceAll("[\\,]", "");
String pattern1 = "[0-9]+\\.{1}[0-9]+";
//Compile the Regular Expression into Pattern and store it in r1 so that the computer can understand the Regular Expression.
Pattern r1 = Pattern.compile(pattern1);
//Match the Regular Expression with the piece (temp1) we read from assignment.csv.
Matcher m1 = r1.matcher(temp1);
String pattern2 = "[0-9]+";
//Compile the Regular Expression into Pattern and store it in r2 so that the computer can understand the Regular Expression.
Pattern r2 = Pattern.compile(pattern2);
//Match the Regular Expression with the piece (temp1) we read from assignment.csv.
Matcher m2 = r2.matcher(temp1);
nums1 = new ArrayList<String>();
//We have two types of numbers - Integer and Decimal
//Let's start us Integer.
//Recollect, m1 is used to match decimal numbers.
if(!(m1.find())){//if a decimal number CAN'T be found
//We use while statement instead of if statement here.
//If there is only one piece per line, we can use either while statement or if statement.
//However, we have to use while statement if there is more than one piece per line.
while(m2.find()) {//if an integer number CAN be found
//If an Integer is found, we add 1 to Variable count.
count++;
//Even though the number (i.e., m2.group(0)) is an Integer, its data type is String. So we store it to a String variable - number.
String number = m2.group(0);
nums1.add(number);
//If the remainder of count by 5 is zero, we display the number and advance to a new line.
if (count % 5 == 0){
//System.out.println(number);
}
//Otherwise, we just display the number on the same line and divide numbers by a space.
else
System.out.println(/*number + " "*/);
}
}
//If we find a decimal number
else{
//We add 1 to Variable count.
count++;
//Even though the number (i.e., m1.group(0)) is a decimal number, its data type is String. So we store it to a String variable - number.
String number = m1.group(0);
nums1.add(number);
//If the remainder of count by 5 is zero, we display the number and advance to a new line.
if (count % 5 == 0){
//System.out.println(number);
}
//Otherwise, we just display the number on the same line and divide numbers by a space.
else
System.out.println(/*number + " "*/);
}
findDuplicates();
}
FILE2.close();//Once we finish the task, we close the file.
}
I tried to delete as much unnecessary code as I could.
EDIT
Expected output should be:
1913 is duplicated 3 times.
2016 is duplicated 2 times.
32843 is duplicated 1 times.
31 is duplicated 2 times.....
EDIT
So I believe i've found the problem. For some reason,
String p = nums.get(k)
in my findDuplicates() method is only returning the value 31, and not the other values. I am working on solving the problem, and will post an answer when I do.
I think the biggest issue is that the printline is inside the second for loop.Furthermore I would remove the boolean and just compare the 2 Strings (p==v).
So the code would look more like this:
public static void main(String[] args) {
// array for second file
for (int n = 0; n < nums1.size(); n++) {
// matches are false by default
int count = 0;
String v = nums1.get(n);
// array for first file
for (int k = 0; k < nums.size(); k++) {
String p = nums.get(k);
// second file contains values from first file
if (p==v) {
count++;
}
}
System.out.println( v + " " + "is duped" + " " + count + " " + "times");
}
}
}
With the changes I made the code runs as intended.You can check out a live demo here.
Output:
1913 is duped 4 times
2016 is duped 3 times
32843 is duped 2 times
31 is duped 2 times
27 is duped 3 times
1.4 is duped 2 times
4 is duped 1 times
7 is duped 1 times
2 is duped 1 times
23 is duped 2 times
You should use the System.out.println statement outside inner loop so that first whole of second arraylist get iterated before number of times the number is duplicated is printled.
You also need to make a few other changes to run the program correctly
for (int n = 0; n < nums.size(); n++) {
// matches are false by default
boolean match = false;
int count = 0;
String v = nums.get(n);
// array for second file
for (int k = 0; k < nums1.size(); k++) {
String p = nums1.get(k);
// second file contains values from first file
if (p.contains(v)) {
// there is a match
match = true;
// when there is a match print out matched values and the number of times they appear in second file
if (match) {
count++;
match = false;
}
}
System.out.println( p + " " + "is duped" + " " + count + " " + "times");
count = 0;
}
}
But still then your logic will not work all case because you are not comparing how many times a number is repeated in first file. You are only comparing second file numbers with first file ones. For the case which you gave in question interchanging the two files after modifying the code as I have mentioned it will work.
please try it on.
package stackoverflow.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test {
public List<Integer> list = new ArrayList<Integer>();
public List<Integer> dup = new ArrayList<Integer>();
public Map<Integer, Integer> hashDup = new HashMap<Integer, Integer>();
public void fileReader() {
File file = new File("/home/john/Documents/file1.txt");
List<Integer> list1 = this.output(file);
File file2 = new File("/home/john/Documents/file2.txt");
List<Integer> list2 = this.output(file2);
for (int i = 0; i < list1.size(); i++) {
int counter = 0;
for (int j = 0; j < list2.size(); j++) {
if (list1.get(i) == list2.get(j)) {
counter++;
}
}
if (!hashDup.containsKey(list1.get(i))) {
hashDup.put(list1.get(i), counter);
System.out.println(" dup " + list1.get(i) + " :" + counter);
}
}
}
public List<Integer> output(File file) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String text = null;
while ((text = reader.readLine()) != null) {
// System.out.println( text);
String[] str = text.split(" ");
for (String string : str) {
list.add(Integer.parseInt(string));
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
}
}
// print out the list
// System.out.println(list.toString());
return list;
}
public static void main(String args[]) {
Test t = new Test();
t.fileReader();
}
}
Related
I'm trying to write a Java program to analyse each string in a string array from a text file and if the number parses to a double, the program prints the word previous to it and the word after. I can't seem to find out how to parse each element of a string array. Currently it will only print the first number and the following word but not the previous word. Hopefully somebody can help.
My text file is as follows:
Suppose 49 are slicing a cake to divide it between 5 people. I cut myself a big slice, consisting of 33.3 percent
of the whole cake. Now it is your turn to cut a slice of cake. Will you also cut a 33.3 percent slice? Or will you
be fairer and divide the remaining 66.6 percent of the cake into 4 even parts? How big a slice will you cut?
Here is my code:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import javax.swing.JOptionPane;
public class NumberSearch {
public static void main(String args[]) throws FileNotFoundException {
//creating File instance to reference text file in Java
// String filedirect = JOptionPane.showInputDialog(null, "Enter your file");
File text = new File("cakeQuestion2.txt");
//Creating Scanner instance to read File in Java
Scanner scnr = new Scanner(text);
//Reading each line of file using Scanner class
int lineNumber = 1;
while(scnr.hasNextLine())
{
String line = scnr.nextLine();
lineNumber++;
//Finding words
String[] sp = line.split(" +"); // "+" for multiple spaces
for (int i = 1; i < sp.length; i++)
{
{
double d = Double.parseDouble(sp[i]);
// System.out.println(+ d);
if (isDouble(sp[i]))
{
// have to check for ArrayIndexOutOfBoundsException
String surr = (i-2 > 0 ? " " + sp[i-2]+" " : "") +
sp[i] +
(i+1 < sp.length ? " "+sp[i+1] : "");
System.out.println(surr);
}
}}
}
}
public static boolean isDouble( String str )
{
try{
Double.parseDouble( str );
return true;
}
catch( Exception e ){
return false;
}}}
Mmmmm... your code seems too verbose and complex for the mission.
Check this snippet:
public static void main(String args[]) throws FileNotFoundException {
String line = "Suppose 49 are slicing a cake to divide it between 5 people. I cut myself a big slice, consisting of 33.3 percent of the whole cake. Now it is your turn to cut a slice of cake. Will you also cut a 33.3 percent slice? Or will you be fairer and divide the remaining 66.6 percent of the cake into 4 even parts? How big a slice will you cut?";
String[] sp = line.split(" +"); // "+" for multiple spaces
final String SPACE = " ";
// loop over the data
for (int i = 0; i < sp.length; i++) {
try {
// if exception is not raised, IS A DOUBLE!
Double.parseDouble(sp[i]);
// if is not first position print previous word (avoid negative index)
if (i > 0)
System.out.print(sp[i - 1] + SPACE);
// print number itself
System.out.print(sp[i] + SPACE);
// if is not last position print previous word (avoid IOOBE)
if (i < sp.length - 1)
System.out.print(sp[i + 1]);
// next line!
System.out.println();
} catch (NumberFormatException ex) {
// if is not a number, not our problem!
}
}
}
RESULT:
Suppose 49 are
between 5 people.
of 33.3 percent
a 33.3 percent
remaining 66.6 percent
into 4 even
I have looked on other such answers with this error and I can't seem to figure out my code specifically. I am using Java, and I am trying to make a program where I enter a number as an input, and as an output I should get:
example input: 1234
The original number is 1234
The number in reverse is 4 3 2 1
I have this code written:
import java.util.Scanner; //Needed for Scanner class
public class CoeQuiz3
{
public static void main(String[] args)
{
//establish variables
String ogNumber;
int ogNumberInt;
Scanner keyboard = new Scanner(System.in); //establish scanner
System.out.println("Enter a positive integer greater than 0.");
ogNumber = keyboard.nextLine();
ogNumber = checknumber(ogNumber);
ogNumberInt = Integer.parseInt(ogNumber);
//print the original number
System.out.println("The original number is " + ogNumber);
//print the reverse number
int ogNumberLength = ogNumber.length();
int digitposition, ogDigit;
String reverseStatement = "The number reversed is ";
for (digitposition = ogNumberLength; digitposition >= 0;
digitposition--)
{
ogDigit = ogNumber.charAt(digitposition);
reverseStatement += ogDigit + " ";
}
System.out.println(reverseStatement);
it compiles and runs, but every time it gives me the error:
The original number is 1234
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of
range: 4
at java.lang.String.charAt(String.java:658)
at CoeQuiz3.main(CoeQuiz3.java:30)
It should work logically - what is the problem? This problem still occurs if I replace >= with >.
You are trying to access one past the highest available character index in your string. Try this loop instead:
for (int i=ogNumber.length()-1; i >=0; i--) {
char chr = ogNumber.charAt(i);
reverseStatement += chr;
}
System.out.println(reverseStatement);
But a nicer way to do this is to use the StringBuffer.reverse() method:
String ogNumberReversed = new StringBuffer(ogNumber).reverse();
for (int i=0; i < ogNumberReversed.length(); ++i) {
char chr = ogNumberReversed.charAt(i);
reverseStatement += chr;
}
System.out.println(reverseStatement);
Alternative solution:
int number = 1234;
String strReversed = new StringBuilder(String.valueOf(number)).reverse().toString().replace("", " ").trim();
System.out.println(strReversed); // 4 3 2 1
Ideone example
See this piece of code
for (digitposition = ogNumberLength; digitposition >= 0;
digitposition--)
{
ogDigit = ogNumber.charAt(digitposition);
reverseStatement += ogDigit + " ";
}
The first parameter of the loop digitposition = ogNumberLength
specifies that the loop should access the char at the position equal to length of the string, and in case of string, the length is equal to the number of characters (for e.g. length of string "HAPPY" would be 5 not 4). But the index of the last element of the String array is one less than the length of the string (as arrays are zero indexed).
So in practice if you have entered the number "1234":
length of string is = 4
position of last element array = 3
So your code is trying to access the element number 4 in an array of last index 3, hence the exception.
You should instead write the following (notice the -1 in the 1st parameter)
for (digitposition = ogNumberLength - 1; digitposition >= 0;
digitposition--)
{
ogDigit = ogNumber.charAt(digitposition);
reverseStatement += ogDigit + " ";
}
This would solve your problem, however if reversing only numbers is your sole objective then I would suggest use the following method as using strings is much more resource intensive
import java.util.Scanner;
class ReverseNumber
{
public static void main(String args[])
{
int n, reverse = 0;
System.out.println("Enter the number to reverse");
Scanner in = new Scanner(System.in);
n = in.nextInt();
while( n != 0 )
{
reverse = reverse * 10;
reverse = reverse + n%10;
n = n/10;
}
System.out.println("Reverse of entered number is "+reverse);
}
}
Cheers!!!
Please change your for-loop as follows:
for (digitposition = ogNumberLength-1; digitposition >= 0; digitposition--){
ogDigit = Character.getNumericValue(ogNumber.charAt(digitposition));
reverseStatement += ogDigit + " ";
}
and see the results.
There are two things which have been added:
The for loop counter should start from ogNumberLength-1 not
ogNumberLength. This was the reason for
java.lang.StringIndexOutOfBoundsException
There is a need to convert the ASCII value of char to number. That is why
Character.getNumericValue() has been used.
Hope, it helps!
Im trying to have this code print 1-10 on first line, then 11-20 on the second, 21-30 on the third, etc.
But with the code now Its printing 1-10 on first line, then 10-20 on the second, 20-30 on the third, etc.
Basically I'm stuck here and have been doing trial and error to try and fix it but nothings working.
import java.util.Scanner;
import java.io.*;
public class P4C {
public static void main ( String [] args )throws IOException {
PrintWriter writer = new PrintWriter ( new File ( "Write100Project" )); //creates a PrintWriter object to allow us to create and write to a file.
int integer = 1;
int margin = 1;
int counter = 1;
while ( margin <=100){
if ( margin == 10*counter ){
System.out.println ( integer + " ");
counter+=1;
integer = integer+1;
}
System.out.print ( integer + " " );
integer+=1;
margin++;
}
}
}
When you loop over an array and want to treat certain elements differently there basically are two approaches:
Do something for the special element. Do something else for everything but the special element. In code this means an if-else in your while loop.
Do something generic for every element and do something extra for the special elements.
Which approach to choose depends on the amount of overlap. If the code for the special element is very different from the code for the other elements, use 1. If the code is almost the same, use 2.
You seem to do a hybrid of these, which is why every multiple of 10 is printed twice. Translating your problem two these approaches:
Print the number and a new line for every multiple of 10. Print the number for every other element. Code snippet of the while body (using %, I hope you got is meaning from the other answers):
if (margin % 10 == 0) {
System.out.println(margin + " ");
margin++;
} else {
System.out.print(margin + " ");
margin++;
}
Print the number for every element. Additionally, print a new line for every multiple of 10 (note how I need to reorder your code; you first want to print the multiple of 10, then the new line, then increment margin):
System.out.print(margin + " ");
if(margin % 10 == 0) {
System.out.println();
}
margin++;
Besides, notice how I don't need integer and counter any more?
With this type of thing the modulus % which shows you the remainder. Here you want a new line after every 10 so #MadProgrammer 's (margin % 10 == 0) is saying when the remainder after dividing it by 10 is 0
You can do this all with one variable instead of using three which should make it a bit simpler. The logic is while your number is less than 100, add one to it then print it out. If it is the 10th number in the row print a new line.
import java.util.Scanner;
import java.io.*;
public class P4C {
public static void main ( String [] args )throws IOException {
PrintWriter writer = new PrintWriter ( new File ( "Write100Project" )); //creates a PrintWriter object to allow us to create and write to a file.
int integer = 0;
while ( integer <100){
if ( integer % 10 == 0 ){ //If integer is divisible by 10
System.out.println (); //Time to go onto a new line
}
integer++;
System.out.print ( integer + " " );
}
}
}
The '%' is modulus.
Modulus basically returns the remainder; for example:
5 % 4 = 1;
3 % 2 = 1;
8 % 3 = 2;
10 % 10 = 0;
i++ is the same as saying either;
i = i + 1;
or
i += 1;
import java.util.Scanner;
import java.io.*;
public class IntegerCounting {
public static void main ( String [] args )throws IOException {
PrintWriter writer = new PrintWriter ( new File ( "Write100Project" ));
int i = 0;
while(i < 100){
if(i % 10 == 0 && i != 0){
System.out.println(i++ + "");
}
System.out.print(i++ + " ");
}
}
}
This may help...
int integer = 1;
while(integer<=100){
System.out.print(" "+integer++);
if(integer%10==0){
System.out.println(" "+integer++);
//System.out.println();
}
}
This is my code to work out the length of a word:
public class WordCount {
public static void main (String args []) {
String text;
text = "Java";
System.out.println (text);
//Work out the length
String [] input = text.split(" ");
int MaxWordLength = 0;
int WordLength = 0;
for (int i = 0; i < input.length; i++)
{
MaxWordLength = input[i].length();
WordLength = MaxWordLength;
} //End of working out length
//Work out no. of words
int[] intWordCount = new int[WordLength + 1];
for(int i = 0; i < input.length; i++) {
intWordCount[input[i].length()]++; }
for (int i = 1; i < intWordCount.length; i++) {
System.out.println("There are " + intWordCount[i] + " words of length " + MaxWordLength);
}
}
}
The problem I am having is that when it prints out the length of the word, I get these results:
Java
There are 0 words of length 4
There are 0 words of length 4
There are 0 words of length 4
There are 1 words of length 4
But when I change the text to "J" this prints out:
J
There are 1 words of length 1
Any idea why it's doing that?
P.S. I'm kind of new to Java and any help would be appreciated.
I am not sure if you want to count letter or word because your code counts letter to me.
Just you need to change this line from
String [] input = text.split(" ");
to
String [] input = text.split("");
and your program works perfectly.
input: Java
output: There are 4 letters of length 1 <- Hope this is the expected result for you
Source: Splitting words into letters in Java
You can achieve this in better and less headache by using Lambda in Java
Code:
import java.util.*;
public class LambdaTest
{
public static void main (String[] args)
{
String[] st = "Hello".split("");
Collection myList = Arrays.asList(st);
System.out.println("your word has " + myList.stream().count() + "letters");
}
}
Output:
your word has 5 letters CLEARLY in length 1
My answer when you cleared what your issue is
Code:
public class WordCount
{
public static void main (String[] args)
{
String text ="";
int wordLenght = 0;
text = "Java is awesome for Me";
System.out.println (text);
String [] input = text.split(" ");
List<Integer> list = new ArrayList<>();
for (int i = 0; i < input.length; i++)
{
list.add(input[i].length());
}
Set<Integer> unique = new HashSet<Integer>(list);
for (Integer length : unique) {
System.out.println("There are " + Collections.frequency(list, length) + " words of length " + length);
}
}
}
output:
There are 2 words of length 2
There are 1 words of length 3
There are 1 words of length 4
There are 1 words of length 7
Note: Read about HashSet and Set in Java
Source: http://javarevisited.blogspot.com/2012/06/hashset-in-java-10-examples-programs.html
Let's walk through this:
public class WordCount {
public static void main (String args []) {
String text;
text = "Java";
text is equal to "Java".
System.out.println (text);
Prints "Java"
//Work out the length
String [] input = text.split(" ");
This splits the string "Java" on spaces, of which there are none. So input (which I'd recommend be renamed to something more indicative, like inputs) is equal to an array of one element, and that one element is equal to "Java".
int MaxWordLength = 0;
int WordLength = 0;
for (int i = 0; i < input.length; i++)
{
MaxWordLength = input[i].length();
For each element, of which there is only one, MaxWordLength is set to the length of the first (and only) element, which is "Java"...whose length is 4.
WordLength = MaxWordLength;
So WordLength is now equal to 4.
} //End of working out length
//Work out no. of words
int[] intWordCount = new int[WordLength + 1];
This creates an int array of [WordLength + 1] elements (which is equal to [4 + 1], or 5), where each is initialized to zero.
for(int i = 0; i < input.length; i++) {
intWordCount[input[i].length()]++; }
For each element in input, of which there is only one, this sets the input[i].length()-th element--the fifth, since input[i] is "Java" and it's length is four--to itself, plus one (because of the ++).
Therefore, after this for loop, the array is now equal to [0, 0, 0, 0, 1].
for (int i = 1; i < intWordCount.length; i++) {
System.out.println("There are " + intWordCount[i] + " words of length " + MaxWordLength);
So this naturally prints the undesired output.
}
}
}
Your output is different when the input is only "J", because the intWordCount array is shortened to input[i].length() elements, which is now 1. But the value of the last element is still set to "itself plus one", and "itself" is initialized to zero (as all int-array elements are), and then incremented by one (with ++).
for (int i = 1; i < intWordCount.length; i++) {
System.out.println("There are " + intWordCount[i] + " words of length " + MaxWordLength);
}
1) You print out words with intWordCount[i] == 0, which is why you have the "There are 0 words of length X"
2) System.out.println("There are " ... + MaxWordLength); should probably be System.out.println("There are " ... + i);, so you have "There are 0 words of length 1" , "There are 0 words of length 2", etc
I know this question has been solved long time ago, but here is another solution using new features of Java 8. Using Java streams the whole exercise can be written in one line:
Arrays.asList(new String[]{"Java my love"}) //start with a list containing 1 string item
.stream() //start the stream
.flatMap(x -> Stream.of(x.split(" "))) //split the string into words
.map((String x) -> x.length()) //compute the length of each word
.sorted((Integer x, Integer y) -> x-y) //sort words length (not necessary)
.collect(Collectors.groupingBy(x -> x, Collectors.counting())) //this is tricky: collect results to a map: word length -> count
.forEach((x,y) -> {System.out.println("There are " + y + " word(s) with " + x + " letter(s)");}); //now print each result
Probably in few year time this would be a preferred method for solving such problems. Anyway it is worth knowing that such alternative exists.
To count words in text with we used Pattern class with while loop:
I. Case Sensitive word counts
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CountWordsInText {
public static void main(String[] args) {
String paragraph = "I am at office right now."
+ "I love to work at office."
+ "My Office located at center of kathmandu valley";
String searchWord = "office";
Pattern pattern = Pattern.compile(searchWord);
Matcher matcher = pattern.matcher(paragraph);
int count = 0;
while (matcher.find()) {
count++;
}
System.out.println(count);
}
}
II. Case Insensitive word counts
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CountWordsInTextCaseInsensitive {
public static void main(String[] args) {
String paragraph = "I am at office right now."
+ "I love to work at oFFicE."
+"My OFFICE located at center of kathmandu valley";
String searchWord = "office";
Pattern pattern = Pattern.compile(searchWord, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(paragraph);
int count = 0;
while (matcher.find())
count++;
System.out.println(count);
}
}
Idk, but using the length method as much as you have to figure out how the length mechanism works is like defining a word using the word. It's an honorable conquest figuring out how the length method works, but you should probably avoid using the length method.
So far this is what I tried:
public class CharacterCounter {
public static void main(String[] args){
String string = "sashimi";
int count = 0;
for(int i =0; i < string.length(); i++){
if(string.charAt(i) == 'i'){
count++;
}
}
System.out.println("The number of letter i is " + count);
}
}
Output:
The number of letter i is 2
But what I wanna do is, the program should count the most occurred characters.
For example here the string is SASHIMI, the output should be:
the number of letter S is 2
the number of letter I is 2
I'm stuck with this problem. I need your help. Thanks.
This would be the fastest way:
final int[] counts = new int[1<<16];
for (char c : <your_string>)
counts[c]++;
(i've just sketched out the part which iterates over all your chars, I believe that's the easy part, and not directly related to this question).
Benchmark results
I've pitted the HashMap approach against mine with three string lengths:
10
1,000
100,000
And these are the results:
Benchmark Mode Thr Cnt Sec Mean Mean error Units
testArray1 thrpt 1 5 5 6.870 0.083 ops/msec
testArray2 thrpt 1 5 5 6.720 0.374 ops/msec
testArray3 thrpt 1 5 5 3.770 0.019 ops/msec
testHashMap1 thrpt 1 5 5 1269.123 251.766 ops/msec
testHashMap2 thrpt 1 5 5 12.776 0.165 ops/msec
testHashMap3 thrpt 1 5 5 0.141 0.005 ops/msec
What do they mean? Yes, initializing a full 512K block of memory to zero is costly. But after that is paid, my array algorithm hardly even notices the thousands of characters whizzing by. The HashMap approach, on the other hand, is much faster for very short strings, but scales dramatically worse. I guess the crossover is at about 2k string length.
I suppose it is not disputed that such character-count statistics are usually run against massive text corpora, and not stuff like your name and surname.
Of course, the performance of the array approach can be improved substantially if you can assume that not the complete UTF-16 codepoint range will be used. For example, if you use an array that accomodates only the lowest 1024 codepoints, the performance rises to 470 ops/msec.
char[] chars = string.toCharArray();
HashMap<Character, Integer> countMap = new HashMap<Character, Integer>();
for (char aChar : chars) {
if (countMap.containsKey(aChar)) {
countMap.put(aChar, countMap.get(aChar) + 1);
} else {
countMap.put(aChar,1);
}
}
//determine max occurence
int max = 0;
for (Integer i: countMap.values()) {
if (max < i) {
max = i;
}
}
//print all satisfiying max occurrence
for (Map.Entry<Character, Integer> e: countMap.entrySet()) {
if (e.getValue() == max) {
System.out.println("The number of letter " + e.getKey() + " is " + max);
}
}
I believe that using primitives would be faster than using HashMap. This works:
public static void main(String[] args)
{
final String string = "sashimi";
final int counters[] = new int[256]; // assuming you would use only ASCII chars
for (final char c : string.toCharArray())
{
counters[c]++;
}
int maxCounter = 0;
for (final int counter : counters)
{
if (maxCounter < counter)
{
maxCounter = counter;
}
}
for (int i = 0; i < counters.length; i++)
{
if (counters[i] == maxCounter)
{
System.out.printf("%c has %d occurences.\n", i, counters[i]);
}
}
}
Output:
i has 2 occurences.
s has 2 occurences.
As mentioned in the comments, a HashMap seems ideal for this, although I won't give you the direct code, I'll give you a pseduo-code template.
for(each letter in a word)
{
if(this letter (l) exists in your hash map)
{
hashmap.put(l, hashmap.get(l) ++);
}
else
{
hashmap.put(l, 1);
}
}
This will give you a hashmap of all letters, mapped to the amount of times they appear in a word. Following your example:
S => 2
A => 1
H => 1
I => 2
M => 1
I suggest you create a TreeSet and then you can have a new class that will store the character and the number of ocurrences, then you can have that class have a compareTo that checks the occurrence and an equals that checks the char. Then whenever you insert them in the treeset they will always be in the order of whichever one appeared the most.
Please let me know if you need help with this or if you can figure it out with this information :)
EDIT: once you have filled the TreeSet with all of the letters, all you have to do is start getting them out 1 by 1 until the occcurence of the one that you took out is less than the one you took before (ie, if the top 3 letters appeared 3 times and the forth one 2, you only display the first 3).
you must take an HashMap to keep the most repeated chars with the repeat time and print it.
What you need to do is to take the literal (string). And look over each char of it and put it to proper bucket. In other words you need to group them.
You could create a bucket for each letter of alphabet. Then you could place the char in proper bucket and at the end count the items in it to have the answer.
See Marko answer, that do this.
Another option is that you sort your literal AHIIMSS, then using simple loop you will be able to write the results.
The method you pick depends the result you need to get. If you need to find how many of each letter ware using in word then sort options is more tide, if you need to pick only the maximum letters then solution with buckets is more useful.
import java.util.*;
public class CharacterCounter {
public static void main(String[] args){
String string = "sashimi";
int count = 0;
ArrayList<Character> c = new ArrayList<Character>();
for(int i =0; i <string.length(); i++)
{
count=0;
if(c.contains(string.charAt(i)))
{
continue;
}
c.add(string.charAt(i));
for(int j = 0;j<string.length();j++)
{
if(string.charAt(j) == string.charAt(i))
{
count++;
}
}
System.out.println("The number of letter "+string.charAt(i)+" is " + count);
}
}
}
String str = "sashimi";
Map<Character,Integer> countMap=new HashMap<Character,Integer>();
Set<Character> maxcSet=new HashSet<Character>();
Character maxC=null;
Integer maxCount=null;
for (int i = 0; i < str.length(); i++) {
char c=str.charAt(i);
Integer tempCount=countMap.get(c);
if(tempCount==null){
tempCount=0;
}
++tempCount;
if(i==0){
maxCount=tempCount;
maxC=c;
}else if(tempCount!=null){
if(maxCount<tempCount){
maxC=c;
maxCount=tempCount;
maxcSet.clear();
maxcSet.add(maxC);
}else if(maxCount==tempCount){
maxcSet.add(c);
}
}
countMap.put(c, tempCount);
}
System.out.println("The number of letter i is " + maxcSet);
import java.util.Scanner;
public class CountingCharecter {
public static void main(String[] args) throws Exception {
///Reading Data String from keyboard
int count=0;
System.out.println("Enter Your String:");
Scanner sc = new Scanner(System.in);
String s1 = sc.nextLine();
//// Reading `Character` Data from Keyboard
System.out.println("Enter an character:");
//Here we read the character from console type cast the character because the read() return type is int
char ch =(char)System.in.read();
for(int i=0;i<s1.length();i++){
char c = s1.charAt(i);
if(c==ch){
count++;
}//if
}//for
System.out.println("The Number of character which you want to search is having: "+count+" Times");
}
}//CharecterCount
/*
input:-
Enter Your String: Manash
Enter an character: a
output:- 2
*/
public static int numberOfOccurence(String yourString, char needle) {
int nb = 0;
for (int i=0; i < yourString.length(); i++)
{
if (yourString.charAt(i) == needle)
nb++;
}
return nb;
}
You can also use Pattern and Matcher :
Pattern pattern = Pattern.compile("i");
Matcher matcher = pattern.matcher("saigigd");
int count = 0;
while (matcher.find())
count++;
System.out.println(count);