Arraylist find the count of consecutive duplicate elements - java

I am trying to find the COUNT of repeated elements in an array list.
for example if array named "answerSheerPacketList" list contains values like {20,20,30,40,40,20,20,20},i need to show output like {20=2,30=1,40=2,20=3}.
Map<String, Integer> hm = new HashMap<String, Integer>();
for (String a : answerSheerPacketList) {
Integer j = hm.getinsAnswerSheetId(a);
hm.put(a, (j == null) ? 1 : j + 1);
}
// displaying the occurrence of elements in the arraylist
for(Map.Entry<String, Integer> val : hm.entrySet()){
System.out.println("Element " + val.getKey() + " "
"occurs" + ": " + val.getValue()+ " times");
}
when i executed above code i got output like {20=5,30=1,40=2} but i am trying to get a output like {20=2,30=1,40=2,20=3}.

A simple approach here would be to just iterate the arraylist once, and then keep tallies as we go along:
List<Integer> list = new ArrayList<>();
list.add(20);
list.add(20);
list.add(30);
list.add(40);
list.add(40);
list.add(20);
list.add(20);
list.add(20);
Integer curr = null;
int count = 0;
System.out.print("{");
for (int val : list) {
if (curr == null) {
curr = val;
count = 1;
}
else if (curr != val) {
System.out.print("(" + curr + ", " + count + ")");
curr = val;
count = 1;
}
else {
++count;
}
}
System.out.print("(" + curr + ", " + count + ")");
System.out.print("}");
{(20, 2)(30, 1)(40, 2)(20, 3)}

This is a classic problem of counting runs of consecutive elements in an array. I have renamed the array to arr in the code for brevity.
int run = 1;
for (int i = 0; i < n; ++i) { // n is the size of array
if (i + 1 < n && arr[i] == arr[i + 1]) {
run++; // increment run if consecutive elements are equal
} else {
System.out.println(arr[i] + "=" + run + ", ");
run = 1; // reset run if they are not equal
}
}
Performance-wise, this approach is aysmptotically optimal and runs in O(n), where n is the number of elements in the array.

Set<Integer> distinctSet = new HashSet<>(answerSheerPacketList);
HashSet<Integer,Integer> elementCountSet=new HashSet<>();
for (Integer element: distinctSet) {
elementCountSet.put(element,Collections.frequency(answerSheerPacketList, element));
}

What you need is basically frequency counting. The following code will do it with a single pass through your answerSheerPacketList array:
int[] answerSheerPacketList = // initialization
Map<Integer, Integer> frequencyCount = new LinkedHashMap<>();
for (int i : answerSheerPacketList) {
Integer key = Integer.valueOf(i);
if (frequencyCount.containsKey(key)) {
frequencyCount.put(key, Integer.valueOf(frequencyCount.get(key) + 1));
} else {
frequencyCount.put(key, Integer.valueOf(1));
}
}
for (Integer key : frequencyCount.keySet()) {
System.out.println("Element " + key + " occurs: " + frequencyCount.get(key)
+ " times");
}

Related

Take a list/array of names and count the number of times each unique name is listed

The input for this code is:
"John, Mary, Joe, John, John, John, Mary, Mary, Steve."
My goal is to print out:
"(Name) got (# of votes) votes."
Ending with a statement of the winner.
I can't seem to debug my code though. This is my code:
static void popularity_contest(List<String> name_list) {
largest_count = "";
largest_count = 0;
int n = name_list.size();
int count = 1;
int y = sorted(name_list);
for(i=1; i<name_list.length; i++){
if (n[i] == n[i-1]){
count += 1;
}
else
{
name = n[i-1];
System.out.println(n[i-1] + " got " + str.length(count) + " votes.");
if (count > largest_count)
{
largest_count = count;
largest_name = name;
count = 1;
}
System.out.println(str.length(y)-1 + " got " + str.length(count) + " votes.");
name = str.length(y)-1;
}
if (count > largest_count)
{
largest_count = count;
largest_name = name;
System.out.print(largest_name + " Wins!");
}
}
}
If you are allowed to use Java 8, this can be done very easily with streams and Collectors.groupingBy() :
Map<String, Long> collect = name_list.stream()
.collect(Collectors.groupingBy(Function.identity(),
Collectors.counting()));
You will get a Map<String, Long> with key representing the name, and value representing the number of times it repeats. Example :
{Tom=2, Timmy=1, Elena=1}
Although this might be too advanced as you are new to java.
I like the answer by #SchiduLuca but I thought I would present a solution not using streams. (In my code there might be a draw between two or more winners)
static void popularity_contest(List<String> name_list) {
Map<String, Integer> result = new HashMap<>();
for (String name : name_list) {
Integer count = result.get(name);
if (count == null) {
count = new Integer(1);
result.put(name, count);
} else {
result.put(name, count + 1);
}
}
//Print result and look for max # votes
Integer maxVotes = new Integer(0);
for (Entry<String, Integer> contestant : result.entrySet()) {
System.out.println(String.format("%s got %d votes", contestant.getKey(), contestant.getValue().intValue()));
if (contestant.getValue() > maxVotes) {
maxVotes = contestant.getValue();
}
}
//Print all winners
System.out.println("*** Winner(s) ***");
for (Entry<String, Integer> contestant : result.entrySet()) {
if (contestant.getValue() == maxVotes) {
System.out.println(String.format("%s got %d votes and is a winner", contestant.getKey(), contestant.getValue().intValue()));
}
}
}
The biggest error lies in your comparison of the names. You are using == to compare strings when you need to use the method equals() or equalsIgnoreCase(). Finally you can just use your list you're given and use the get() method when accessing the element at a particular index.
if (name_list.get(i).equalsIgnoreCase(name_list.get(i-1))
{
count += 1;
}

HashMap Object array data gets replaced

I am adding data into HashMap where node is an object with variables index and successor.
private static HashMap <Integer, node> peerList = new HashMap<Integer, node>();
public void generateFingerTable (int node_position) {
chordSize = chord.initChordSize;
chord chord = new chord();
//create new node and add to map
node newPeer = new node();
peerList.put(node_position, newPeer);
for (int i=0; i<chordSize; i++) {
int temp = i+1;
newPeer.index = new int [chordSize];
newPeer.successor = new int [chordSize];
int temp1 = node_position + (int)Math.pow(2, temp-1) % chord.getChordSize();
peerList.get(node_position).index[i] = temp;
peerList.get(node_position).successor[i] = temp1;
System.out.println ("Index: " + newPeer.index[i] + "\n" + "Successor: " +
newPeer.successor[i]);
}
}
public void printFingerTable() {
for (Map.Entry<Integer, node> m : peerList.entrySet()) {
System.out.println ("Peer " + m.getKey() + " with Index: " + m.getValue().getIndex() + " Successor: " +
m.getValue().getSuccessor());
}
When I print the Hash details, the result shows Index: [0,0,0,0,5] , Successor:[0,0,0,0,16] which means the previously added elements gets replaced and only the last element is saved in Hashmap.
The intended result should be Index [1,2,3,4,5], Successor: [1,2,4,8,16].
How can I amend this so the data don't get replaced?
You initialize the index and successor arrays in each iteration of the loop, so only the value of the last index remains in the end, and the others are 0.
You should initialize the arrays before the loop.
Change the code to :
public void generateFingerTable (int node_position) {
chordSize = chord.initChordSize;
chord chord = new chord();
//create new node and add to map
node newPeer = new node();
peerList.put(node_position, newPeer);
newPeer.index = new int [chordSize];
newPeer.successor = new int [chordSize];
for (int i=0; i<chordSize; i++) {
int temp = i+1;
int temp1 = node_position + (int)Math.pow(2, temp-1) % chord.getChordSize();
peerList.get(node_position).index[i] = temp;
peerList.get(node_position).successor[i] = temp1;
System.out.println ("Index: " + newPeer.index[i] + "\n" + "Successor: " +
newPeer.successor[i]);
}
}
I think you should use a different data-type or structure than HashMap as HashMaps do not guarantee order. I am pointing this out as your code peerList.put(node_position, newPeer); seems to imply you are setting the position of your object in your HashMap but that is not the case. I only say this because you are just using the variable called node_postion to key or hash where your data object will live in your HashMap. See this link for more details.
Difference between HashMap, LinkedHashMap and TreeMap

Add method for a PositionalList

I need to create an add method for a PositionalList... It uses an Array to store data. Here is the private members and the constructor:
private static int DEFAULT_CAPACITY = 10;
private Object[] items;
private int listSize;
private int curPos;
private int lastItemPos;
public FSAPositionalList(){
items = new Object[DEFAULT_CAPACITY];
listSize= 0;
curPos = 0;
lastItemPos = -1;
}
Psuedo-Code for the method that I made up is:
1.) Check for Array OOB.
2.) Create Temporary Array From Current Position -> End of the List
3.) Add item at Current Position
4.) Re-add items from the Temporary Array starting at curPos+1.
Here is my current code for the method:
public void add(Object obj){
// Check For Out of Bounds
if(listSize+1 > DEFAULT_CAPACITY){
throw new RuntimeException("Too many items.");
}else{
//if first time then otherwise
if(listSize == 0){
System.out.println("Permission Granted");
items[curPos] = obj;
listSize++;
return;
}
System.out.println("Access");
// Create temp array from curPos --> end
Object temp[] = new Object[listSize-curPos];
//populate temp array
int counter = 0;
for(int i = curPos; i<listSize; i++){
temp[counter] = items[i];
System.out.print("Temp - " + temp[counter]);
counter++;
}
System.out.println();
// Insert obj
items[curPos] = obj;
System.out.println(" Temp Array: ");
for(int i = 0; i < temp.length; i++){
System.out.println(temp[i]);
}
// re-add temparray after obj
int c = 0;
for(int i = curPos+1; i<listSize; i ++){
System.out.println("Replacing " + i + " " + items[i] + " with " + temp[c]);
items[i] = temp[c];
c++;
}
listSize++;
}
Using a Tester Class as follows:
FSAPositionalList list = new FSAPositionalList();
System.out.println("Adding 1");
list.add(1);
System.out.println(" List : " + list);
System.out.println("Adding 2");
list.add(2);
System.out.println(" List : " + list);
System.out.println("Adding 3");
list.add(3);
System.out.println(" List : " + list);
System.out.println("Adding 66");
list.next();
list.add(66);
System.out.println(" List : " + list);
System.out.println(list);
I have gotten this output:
Adding 1
Permission Granted
List : 1
Adding 2
Access
Temp - 1
Temp Array:
1
List : 2 null
Adding 3
Access
Temp - 2Temp - null
Temp Array:
2
null
Replacing 1 null with 2
List : 3 2 null
Adding 66
Access
Temp - 2Temp - null
Temp Array:
2
null
Replacing 2 null with 2
List : 3 66 2 null
3 66 2 null
I'm not sure why it won't re-add the Temp Array of "1" back to the List afterwords. Can anyone help?
Found a better solution if anyone is ever looking for it:
if (isFull())
throw new RuntimeException("The list is full");
for (int i = listSize - 1; i >= curPos; i--) //Open a space in
items[i + 1] = items[i]; //the array
items[curPos] = obj; //and insert obj in this space
lastItemPos = -1; //Block remove and set until after a successful
//next or previous
listSize++;

Listing all the combinations of the elements of a set

Among elements of a set, I want to list all the 3-combinations of this set.
Is there a way to do it?
If it was a list;
for(int i=0; i<list.size()-2; i++)
for(int j=i+1; j<list.size()-1; j++)
for(int k=j+1; k<list.size(); k++)
System.out.println(list.get(i) + " " + list.get(j) + " " + list.get(k));
But how to do this with a set without converting it to a list?
Converting to a list and using the logic from your code would be my first choice. If you want to do it without converting to list, you can do it with iterators, like this:
Set<String> set = ...;
for (String a : set) {
boolean bGo = false;
for (String b : set) {
if (bGo) {
boolean cGo = false;
for (String c : set) {
if (cGo) {
System.out.println(a + " " + b + " " + c);
} else if (b.equals(c)) {
cGo = true;
}
}
} else if (a.equals(b)) {
bGo = true;
}
}
}
The logic above freely iterates the set in the outer loop. When it starts iterating the set in the first nested loop, it skips elements until the current element of the outer loop is found (i.e. until a.equals(b)). After that, it runs the third nested loop, which skips all data in the set until b, at which point it starts producing the combinations output.
Here is a demo on ideone.
Is your set a SortedSet ? If so, you can do this:
for (V x: mySet) {
for (V y: mySet.tailSet(x, false)) {
for (V z: mySet.tailSet(y, false)) {
System.out.println(x + " " + y + " " + z);
}
}
}

Why are these array elements null?

I have an array which has been initialised with another.
a1 = a2; //right hand side is actually a method returning an array
I can append the returned array elements to a JTextArea but printing them out produces null in the console.
for (int i = 0; i < a1.lenght; i++) {
outputTextArea.append(a1[i]);
System.out.println(a1[i]);
}
Why is this? Thank you.
This is the method:
public String[] searchString(ArrayList<String> content, String string){
stringArray = new String[content.size()];
for(int i = 0; i < content.size(); i++){
if(string.equals(content.get(i))){
if(content.indexOf(string) == 0) {
stringArray[i] = content.get(i) + " " + content.get(i+1) + "\n";
} else if ((content.indexOf(string) > 0) && (content.indexOf(string) < (content.size()-1))) {
stringArray[i] = content.get(i-1) + " " + content.get(i) + " " + content.get(i + 1) + "\n";
} else if ((content.indexOf(string)) == (content.size()-1)) {
stringArray[i] = content.get(i -1) + " " + content.get(i);
}
}
}
return stringArray;
}
The Output NULL not from a1 but from a2
you have if statement :
if (string.equals(content.get(i))) {
.....
}
without else , so if the string != content.get(i) , so it will return null in this index at (a2)
so you may need to initialize a2 with values , or make check like this : if(a1[i] != null)
for(int i = 0; i < a1.lenght; i++){
if(a1[i]!=null){///////////to avoid the null values
outputTextArea.append(a1[i]);
System.out.println(a1[i]);
}
}
the second problem you will face in this code (When you repeated your string in content array):
stringArray[i] = content.get(i) + " " + content.get(i + 1) + "\n";
if i = content.size() ,so ( i+1 ) will IndexOutOfBoundsException

Categories