Apply a Frequency to an Element in an Array - java

I am trying to make a script that will take a set of Words (custom class), organize them alphabetically into an array by their text value (this part works). From here I was going to count how many terms ahead of it are the same as it, and that will be the frequency for all those similar terms. Then it continues to do this till each element in the array has been assigned a frequency. From here it re sorts the elements back into their original position provided a pre stored variable that holds their original element order. Here is the code:
public void setFrequencies() {
List<Word> dupeWordList;
dupeWordList = new ArrayList<>(wordList);
dupeWordList.removeAll(Collections.singleton(null));
Collections.sort(dupeWordList, (Word one, Word other) -> one.getValue().compareTo(other.getValue()));
int count;
int currElement;
for(currElement = 0; currElement < dupeWordList.size(); currElement++) {
count = 1;
Word tempWord = dupeWordList.get(currElement);
tempWord.setFrequency(count);
if(currElement+1 <= dupeWordList.size() - 1) {
Word nextWord = dupeWordList.get(currElement+1);
while(tempWord.getValue().equals(nextWord.getValue())) {
count++;
currElement++;
tempWord.setFrequency(count);
for(int e = 0; e < count - 1; e++) {
Word middleWord = new Word();
if(currElement-count+2+e < dupeWordList.size() - 1) {
middleWord = dupeWordList.get(currElement-count+2+e);
}
middleWord.setFrequency(count);
}
if(currElement+1 <= dupeWordList.size() - 1) {
nextWord = dupeWordList.get(currElement+1);
} else {
break;
}
}
break;
}
}
List<Word> reSortedList = new ArrayList<>(wordList);
Word fillWord = new Word();
fillWord.setFrequency(0);
fillWord.setValue(null);
Collections.fill(reSortedList, fillWord);
for(int i = 0; i < dupeWordList.size(); i++) {
Word word = dupeWordList.get(i);
int wordOrder = word.getOrigOrder();
reSortedList.set(wordOrder, word);
}
System.out.println(Arrays.toString(DebugFreq(reSortedList)));
setWordList(reSortedList);
}
public int[] DebugFreq(List<Word> rSL) {
int[] results = new int[rSL.size()];
for(int i=0; i < results.length; i++) {
results[i] = rSL.get(i).getFrequency();
}
return results;
}
As you can see I set up a little debug method at the bottom. When I run this method is shows that every word was given a frequency of 1. I cant see the issue in my code, nor does it get any errors. Keep in mind I have had it display the sorted dupeWordList and it does correctly alphabetize and their are consecutive duplicate elements in it so this should not be happening.

So If I understand you correctly.. below code would be your solution.
Okay You have a list which is having a strings (terms or words) which are sorted in alphabetical Order.
// Okay the below list is already sorted in alphabetical order.
List<String> dupeWordList = new ArrayList<>(wordList);
To count the Frequency of words in your list, Map<String, Integer> might help you as below.
//Take a Map with Integer as value and String as key.
Map<String,Integer> result = new HashMap<String,Integer> ();
//Iterate your List
for(String s : dupeWordList)
{
if(map.containskey(s))
{
map.put(s,map.get(s)+1);
// Please consider casting here.
}else
{
map.put(s,1);
}
}
Okay now we have a map which is having the frequency of your words or terms as value in your map.
Hope it helps.

Related

i want to count occurrence of each word in a given sentence in java

beginner at java was asked in an interview
here i have to count the occurrence of each word in a given sentence.
for eg( "chair is equal to chair but not equal to table."
Output : chair :2,
is :1,
equal :2,
to :2,
but :1,
not :1,
table :1 )
I have written some part of the code and tried using for loop but i failed....
public static void main(String[] args)
{
int counter = 0;
String a = " To associate myself with an organization that provides a challenging job and an opportunity to provide innovative and diligent work.";
String[] b =a.split(" "); //stored in array and splitted
for(int i=0;i<b.length;i++)
{
counter=0;
for(int j<b.length;j>0;j--)
{
if(b[i] = b[j])
//
}
}
}
}
Use a hashmap to count frequency of objects
import java.util.HashMap;
import java.util.Map.Entry;
public class Funly {
public static void main(String[] args) {
int counter = 0;
String a = " To associate myself with an organization that provides a challenging job and an opportunity to provide innovative and diligent work.";
String[] b = a.split(" "); // stored in array and splitted
HashMap<String, Integer> freqMap = new HashMap<String, Integer>();
for (int i = 0; i < b.length; i++) {
String key = b[i];
int freq = freqMap.getOrDefault(key, 0);
freqMap.put(key, ++freq);
}
for (Entry<String, Integer> result : freqMap.entrySet()) {
System.out.println(result.getKey() + " " + result.getValue());
}
}
}
Quite easy since Java8:
public static Map<String, Long> countOccurrences(String sentence) {
return Arrays.stream(sentence.split(" "))
.collect(Collectors.groupingBy(
Function.identity(), Collectors.counting()
)
);
}
I would also remove non literal symbols, and convert to lowecase before running:
String tmp = sentence.replaceAll("[^A-Za-z\\s]", "");
So your final main method for interview will be:
ppublic static void main(String[] args) {
String sentence = "To associate myself with an organization that provides a challenging job and an opportunity to provide innovative and diligent work.";
String tmp = sentence.replaceAll("[^A-Za-z\\s]", "").toLowerCase();
System.out.println(
countOccurrences(tmp)
);
}
Output is:
{diligent=1, a=1, work=1, myself=1, opportunity=1, challenging=1, an=2, associate=1, innovative=1, that=1, with=1, provide=1, and=2, provides=1, organization=1, to=2, job=1}
A simple (but not very efficient) way would be to add all the elements to a set, which doesn't allow duplicates. See How to efficiently remove duplicates from an array without using Set. Then iterate through the set and count the number of occurrences in your array, printing out the answer after each set element you check.
There are several solutions to this and I'm not going to provide you with any of them. However, I'm going to give you a rough outline of one possible solution:
You could use a Map, for example a HashMap, where you use the words as keys and the number of their occurrence as values. Then, all you need to do is to split the input string on spaces and iterate over the resulting array. For each word, you check if it already exists in the map. If so you increase the value by one, otherwise you add the word to the map and set the value to 1. After that, you can iterate over the map to create the desired output.
You need to use Map data structure which stores data in key-value pairs.
You can use the HashMap (implementation of Map) to store each word as key and their occurance as the value inside the Map as shown in the below code with inline comments:
String[] b =a.split(" "); //split the array
Map<String, Integer> map = new HashMap<>();//create a Map object
Integer counter=null;//initalize counter
for(int i=0;i<b.length;i++) { //loop the whole array
counter=map.get(b[i]);//get element from map
if(map.get(b[i]) == null) { //check if it already exists
map.put(b[i], 1);//not exist, add with counter as 1
} else {
counter++;//if already eists, increment the counter & put to Map
map.put(b[i], counter);
}
}
Using simple For loops
public static void main(String[] args) {
String input = "Table is this Table";
String[] arr1 = input.split(" ");
int count = 0;
for (int i = 0; i < arr1.length; i++) {
count = 0;
for (int j = 0; j < arr1.length; j++) {
String temp = arr1[j];
String temp1 = arr1[i];
if (j < i && temp.contentEquals(temp1)) {
break;
}
if (temp.contentEquals(temp1)) {
count = count + 1;
}
if (j == arr1.length - 1) {
System.out.println(">>" + arr1[i] + "<< is present >>" + count + "<< number of times");
}
}
}
}

location and repetition of characters within a string

Hi biologist here with a little bit of coding background. my goal is to be able to input a string of characters and the code to be able to tell me how many times they occur and at what location in the string.
so ill be entering a string and i want the location and abundance of sq and tq within the string. with the location being the first character e.g njnsqjjfl sq would be located at postition 4.
This is what ive come up with so far (probably very wrong)
string S = "...";
int counter =0;
for(int i=0; i<s.length; i++){
if(s.charAt (i) == 'sq')}
counter++;})
string S = "...";
int counter =0;
for(int i=0; i<s.length; i++){
if(s.charAt (i) == 'tq')}
counter++;})
any input will help, thankyou
So , you can have multiple occurrences of "sq" and "tq" in your code, so you can have 2 arraylists to save these two separately(or one to save them together).
ArrayList<Integer>sqLocation = new ArrayList<>();
ArrayList<Integer>tqLocation = new ArrayList<>();
for(int i =0;i<s.length()-1;i++){
if(s.charAt(i)=='s' && s.charAt(i+1)=='q'){
sqLocation.add(i);
}
else if(s.charAt(i)=='t' && s.charAt(i+1)=='q'){
tqLocation.add(i);
}
}
System.out.println("No. of times sq occurs = "+sqLocation.size());
System.out.println("Locations ="+sqLocation);
System.out.println("No. of times tq occurs = "+tqLocation.size());
System.out.println("Locations ="+tqLocation);
This can be achieved using regex. Your use case is to count occurrences and position of those occurrences. The method match returns an integer list which is position and count is size of list
Exmaple code
public class RegexTest {
public static List<Integer> match(String text, String regex) {
List<Integer> matchedPos = new ArrayList<>();
Matcher m = Pattern.compile("(?=(" + regex + "))").matcher(text);
while(m.find()) {
matchedPos.add(m.start());
}
return matchedPos;
}
public static void main(String[] args) {
System.out.println(match("sadfsagsqltrtwrttqsqsqsqsqsqs", "sq"));
System.out.println(match("sadfsagsqltrtwrttqksdfngjfngjntqtqtqtqtqtq", "tq"));
}
}
what you want is a HashMap <String, List <Integer>>
this will hold, the String that you are looking for e.g. sq or tq, and a List of the positions that they are at.
You want to loop around using String.indexOf see https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#indexOf(java.lang.String,%20int)
psuedocode being
String contents = "sadfsagsqltrtwrttqksdfngjfngjntqtqtqtqtqtq";
map.add (lookFor, new ArrayList ());
int index = 0;
while ((index = contents.indexOf (lookFor, index)) != -1) {
list = map.get (lookFor);
list.add (index);
}
You should use not charAt but substring to get a part of String.
int count(String s, String target) {
int counter = 0;
int tlen = target.length();
for (int i = tlen; i < s.length(); i++) {
if (s.substring(i - tlen, i).equals(target)) {
counter++;
}
}
return counter;
}
// in some method
count("...", "sq");
count("...", "tq");

Java, removing elements from an ArrayList

I'm having an issue with this project. The basic premise is user enters a phrase and it's supposed to find any duplicate words and how many there are.
My issue is when entering just one word multiple times, such as...
hello hello hello hello hello
The output for that would be;
"There are 2 duplicates of the word "hello" in the phrase you entered."
"There are 1 duplicates of the word "hello" in the phrase you entered."
This only seems to happen in situations like this. If I enter in a random phrase with multiple words thrown in through out, it displays the correct answer. I think the problem has something to do with removing the duplicate words and how many times it iterates through the phrase, but I just cannot wrap my head around it. I've added print lines everywhere and have changed the times it iterates all sorts of ways, I through it in a Java Visualizer and still couldn't find the exact problem. Any help is greatly appreciated!
This is for an assignment for my online Java course, but it's only for learning/practice it does not go towards my major. I'm not looking for answers though just help.
public class DuplicateWords {
public static void main(String[] args) {
List<String> inputList = new ArrayList<String>();
List<String> finalList = new ArrayList<String>();
int duplicateCounter;
String duplicateStr = "";
Scanner scan = new Scanner(System.in);
System.out.println("Enter a sentence to determine duplicate words entered: ");
String inputValue = scan.nextLine();
inputValue = inputValue.toLowerCase();
inputList = Arrays.asList(inputValue.split("\\s+"));
finalList.addAll(inputList);
for(int i = 0; i < inputList.size(); i++) {
duplicateCounter = 0;
for(int j = i + 1; j < finalList.size(); j++) {
if(finalList.get(i).equalsIgnoreCase(finalList.get(j))
&& !finalList.get(i).equals("!") && !finalList.get(i).equals(".")
&& !finalList.get(i).equals(":") && !finalList.get(i).equals(";")
&& !finalList.get(i).equals(",") && !finalList.get(i).equals("\"")
&& !finalList.get(i).equals("?")) {
duplicateCounter++;
duplicateStr = finalList.get(i).toUpperCase();
}
if(finalList.get(i).equalsIgnoreCase(finalList.get(j))) {
finalList.remove(j);
}
}
if(duplicateCounter > 0) {
System.out.printf("There are %s duplicates of the word \"%s\" in the phrase you entered.", duplicateCounter, duplicateStr);
System.out.println();
}
}
}
}
Based on some suggestions I edited my code, but I'm not sure I'm going in the right direction
String previous = "";
for(Iterator<String> i = inputList.iterator(); i.hasNext();) {
String current = i.next();
duplicateCounter = 0;
for(int j = + 1; j < finalList.size(); j++) {
if(current.equalsIgnoreCase(finalList.get(j))
&& !current.equals("!") && !current.equals(".")
&& !current.equals(":") && !current.equals(";")
&& !current.equals(",") && !current.equals("\"")
&& !current.equals("?")) {
duplicateCounter++;
duplicateStr = current.toUpperCase();
}
if(current.equals(previous)) {
i.remove();
}
}
if(duplicateCounter > 0) {
System.out.printf("There are %s duplicates of the word \"%s\" in the phrase you entered.", duplicateCounter, duplicateStr);
System.out.println();
}
}
Your problem with your code is that when you remove an item, you still increment the index, so you skip over what would be the next item. In abbreviated form, your code is:
for (int j = i + 1; j < finalList.size(); j++) {
String next = finalList.get(i);
if (some test on next)
finalList.remove(next);
}
after remove is called, the "next" item will be at the same index, because removing an item directly like this causes all items to the right to be shuffled 1 place left to fill the gap. To fix, you should add this line after removing:
i--;
That would fix your problem, however, there's a cleaner way to do this:
String previous = "";
for (Iterator<String> i = inputList.iterator(); i.hasNext();) {
String current = i.next();
if (current.equals(previous)) {
i.remove(); // removes current item
}
previous = current;
}
inputList now has all adjacent duplicates removed.
To remove all duplicates:
List<String> finalList = inputList.stream().distinct().collect(Collectors.toList());
If you like pain, do it "manually":
Set<String> duplicates = new HashSet<>(); // sets are unique
for (Iterator<String> i = inputList.iterator(); i.hasNext();)
if (!duplicates.add(i.next())) // add returns true if the set changed
i.remove(); // removes current item
I would start by populating a Map<String, Integer> with each word; increment the Integer each time you encounter a word. Something like
String inputValue = scan.nextLine().toLowerCase();
String[] words = inputValue.split("\\s+");
Map<String, Integer> countMap = new HashMap<>();
for (String word : words) {
Integer current = countMap.get(word);
int v = (current == null) ? 1 : current + 1;
countMap.put(word, v);
}
Then you can iterate the Map entrySet and display every key (word) where the count is greater than 1. Something like,
String msgFormat = "There are %d duplicates of the word \"%s\" in "
+ "the phrase you entered.%n";
for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
if (entry.getValue() > 1) {
System.out.printf(msgFormat, entry.getValue(), entry.getKey());
}
}
Before you add inputList to finalList, remove any duplicate items from inputList.

Counting occurrences in a string array and deleting the repeats using java

i'm having trouble with a code. I have read words from a text file into a String array, removed the periods and commas. Now i need to check the number of occurrences of each word. I managed to do that as well. However, my output contains all the words in the file, and the occurrences.
Like this:
the 2
birds 2
are 1
going 2
north 2
north 2
Here is my code:
public static String counter(String[] wordList)
{
//String[] noRepeatString = null ;
//int[] countArr = null ;
for (int i = 0; i < wordList.length; i++)
{
int count = 1;
for(int j = 0; j < wordList.length; j++)
{
if(i != j) //to avoid comparing itself
{
if (wordList[i].compareTo(wordList[j]) == 0)
{
count++;
//noRepeatString[i] = wordList[i];
//countArr[i] = count;
}
}
}
System.out.println (wordList[i] + " " + count);
}
return null;
I need to figure out 1) to get the count value into an array.. 2) to delete the repetitions.
As seen in the commenting, i tried to use a countArr[] and a noRepeatString[], in hopes of doing that.. but i had a NullPointerException.
Any thought on this matter will be much appreciated :)
I would first convert the array into a list because they are easier to operate on than arrays.
List<String> list = Arrays.asList(wordsList);
Then you should create a copy of that list (you'll se in a second why):
ArrayList<String> listTwo = new ArrayList<String>(list);
Now you remove all the duplicates in the second list:
HashSet hs = new HashSet();
hs.addAll(listTwo);
listTwo.clear();
listTwo.addAll(hs);
Then you loop through the second list and get the frequency of that word in the first list. But first you should create another arrayList to store the results:
ArrayList<String> results = new ArrayList<String>;
for(String word : listTwo){
int count = Collections.frequency(list, word);
String result = word +": " count;
results.add(result);
}
Finally you can output the results list:
for(String freq : results){
System.out.println(freq);}
I have not tested this code (can't do that right now). Please ask if there is a problem or it doesnÄt work. See these questions for reference:
How do I remove repeated elements from ArrayList?
One-liner to count number of occurrences of String in a String[] in Java?
How do I clone a generic List in Java?
some syntax issues in your code but works fine
ArrayList<String> results = new ArrayList<String>();
for(String word : listTwo){
int count = Collections.frequency(list, word);
String result = word +": "+ count;
results.add(result);
}

NullPointerException error while trying to remove a string word from an Array in a remove() method

I'm making this method remove() which takes a String word as argument, to delete from a global Array "words", but I keep getting a NullPointerException for some reason I cannot find, been stuck for hours.
Basically I check for if the word is in the first position, else if is in the last position, or else if it is in neither so I check all the array, and add the first half before the position of the word, and then add the second half after the position of the word in the array, as to skip it and "delete it". But I'm getting a NullPointerException in the for loop looking for the position of the word in the array. Code for the method is here:
public void remove(String a){
String[] temp_arr = new String[words.length-1]; // make array with 1 less length for deleted
if(words[0].equals(a)){ // if the word is the first in the array
for(int x=0, z=1; x<temp_arr.length; x++,z++)
temp_arr[x]=words[z];
words = temp_arr;
} else if(words[words.length-1].equals(a)){ // if the word is in the last position of the array
for(int x=0, z=0; x<temp_arr.length; x++,z++)
temp_arr[x] = words[z];
words = temp_arr;
} else{ // if the word is in neither first or last position of array
// THIS IS WHERE the exception is thrown, in this for loop, in the if(words[k].equals(a))
int k=0;
for (; k<words.length; k++){ // find the position of the word to delete
if (words[k].equals(a)) {
break;
}
}
for (int i = 0; i < k-1; i++){ // add first part of array before the word
temp_arr[i] = words[i];
}
for(int c = k, b = k+1; c< temp_arr.length; c++,b++){
temp_arr[c] = words[b];
}
words = temp_arr; // assign the new values to global array
}
}
Also, if theres any suggestions for good coding practice would be appreciated, thanks!
** I can only use Arrays as my data structure for this method.
Modify the condition like this
a.equals(words[0])
because you know the string value a. But dont know what value will come from array. So even null value comes from the array it does allow the null pointer exception.
I run your code and find a few errors, I correct somethings without changing the core idea:
} else { // if the word is in neither first or last position of array
// THIS IS WHERE the exception is thrown, in this for loop.
int k = -1;
for (int i = 0; i < words.length; i++) { // find the position of the word to delete
if (words[i].equals(a)) {
k=i;
break;
}
}
if(k<0)//if not exists
return;
for (int i = 0; i < k /*- 1*/; i++) { // add first part of array before the word
temp_arr[i] = words[i];
}
for (int i = k; i < temp_arr.length; i++) {
temp_arr[i] = words[i+1];
}
words = temp_arr; // assign the new values to global array
}
If the original array could't have null elements I would do like this:
public static String[] remove(String words[] , String a) {
int counter = 0;
for (int i = 0; i < words.length; i++) {
if( a.equals(words[i]) ){
words[i] = null;
counter++;
}
}
if(counter==0){
return words;
}
String[] words2 = new String[words.length - counter];
int i=0;
for (String string : words) {
if(string!=null){
words2[i++]=string;
}
}
return words2;
}
I would do that like this:
public void remove(String a) {
List<String> tmp = new ArrayList<String>();
for (String word : words) {
if ((word != null) && (word.equals(a))) {
continue;
}
tmp.add(word);
}
words = tmp.toArray(new String[]);
}
I have a question for you:
Why oh why are you using an array? You should always use a collection (eg a List) unless you absolutely have to use an array (which is rare indeed).
If it were a List, you wouldn't even need this method, because List has the remove() method that does all this for you!

Categories