Jullix993
Jullix993

Reputation: 105

Counting and removing duplicates in an array c

Let's say I have an array with [2,4,6,7, 7, 4,4] I want a program that can iterate through, and then print out something like this:

Value:     Count:
2          1
4          3
6          1
7          2

I don't want it to print out ex 4 three times. What I got so far:

for (int i = 0; i < numberOfInts; i++)
{
    dub[i] = 0;
    for (int y = 0; y < numberOfInts; y++)
    {
        if (enarray[i] == enarray[y])
        {

            dub[i]++;
        }
    }

}

So basically I check each element in the array against all the elements, and for every duplicate I add one to the index in the new array dub[]. So if I ran this code with the example array above, and then printed it out with I'd get something like this: 1,3,1,2,2,3,3. These are pretty confusing numbers, because I don't really know which numbers these belong to. Especially when I'll randomize the numbers in the array. And then I have to remove numbers so I only have one of each. Anyone got a better solution?

Upvotes: 1

Views: 1786

Answers (7)

alk
alk

Reputation: 70911

  1. sort the array, typically by using the qsort() function
  2. iterate over all elements counting successively equal elements and if the next different element is detected print the count of the former

This works on any number of different elements. Also no second array is needed.

Upvotes: 1

Lukas
Lukas

Reputation: 3433

You can iterate through the array while checking for each element if it has been repeated in which case you increment it's count (the loop checks only values a head saving processing time). This let you accomplish what you needed without creating any extra buffer array or structure.

The bool 'bl' prevents repeated printing

int main() {

    int arr[] = { 2, 4, 6, 7, 7, 4, 4 };
    int size = (sizeof(arr) / sizeof(int));

    printf("Value:\tCount\n");
    for (int i = 0; i < size; i++) {
        int count = 0, bl = 1; //or 'true' for print
        //check elements ahead and increment count if repeated value is found 
        for (int j = i; j < size; j++) {
            if (arr[i] == arr[j]) {
                count++;
            }
        }
        //check if it has been printed already
        for (int j = i-1; j >= 0; j--) {
            if (arr[i] == arr[j]) {
                bl = 0; //print 'false'
            }
        }
        if (bl) { printf("%d\t\t%d\n", arr[i], count); } 
    }

    return 0;
}

Upvotes: 2

codemedian
codemedian

Reputation: 127

I don't understand the complexity here. I think there are two approaches that are performant and easy to implement:

Counting Sort

  • requires int array of size of the biggest element in your array
  • overall complexity O(n + m) where m is the biggest element in your array

qsort and enumeration

  • qsort works in O(n * log(n)) and gives you a sorted array
  • once the array is sorted, you can simply iterate over it and count
  • overall complexity O(n*log(n))

Upvotes: 1

emi
emi

Reputation: 3070

What you're asking for is strange. Normally, I'd create a struct with 2 members, like 'number' and 'count'. But let's try exactly what you're asking for (unidimensional array with each number followed by it's count):

int 
   i,
   numberOfInts = 7,
   numberOfDubs = 0,
   enarray[7] = {2,4,6,7,7,4,4},
   dub[14]; // sizeof(enrray) * 2 => maximum number of dubs (if there are no duplicates)

// For every number on enarray
for(i = 0; i < numberOfInts; i++)
{
    int jump = 0;

    // Check if we have already counted it
    // Only check against pairs: Odds are the dub counter
    for(int d = 0; d < numberOfDubs && !jump; d += 2)
    {
       if(dub[d] == enarray[i])
       {
          jump = 1;
       }
    }

    // If not found, count it
    if(!jump)
    {
       // Assign the new number
       dub[numberOfDubs] = enarray[i];
       dub[numberOfDubs + 1] = 1;

       // We can begin from 'i + 1'
       for(int y = i + 1; y < numberOfInts; y++)
       {
          if(enarray[i] == enarray[y])
          {
               dub[numberOfDubs + 1]++;
          }
       }

       // Increment dub's counter by 2: number and it's counter
       numberOfDubs += 2;
    }
}

// Show results
for(i = 0; i < numberOfDubs; i += 2)
{
   printf("%d repeated %d time%s\n", dub[i], dub[i + 1], (dub[i + 1] == 1 ? "" : "s"));
}

Upvotes: 0

Irshad
Irshad

Reputation: 222

Put a print statement in the outer for loop to print value and repetition

for (int i = 0; i < numberOfInts; i++)
{
    dub[i] = 0;
    for (int y = 0; y < numberOfInts; y++)
    {
        if (enarray[i] == enarray[y])
        {

            dub[i]++;
        }
    }
printf("%d%d",enarray[i], dub[i]);
}

Upvotes: 0

user3386109
user3386109

Reputation: 34829

You have the general idea. In addition to your input array, I would suggest three more arrays:

  • a used array that keeps track of which entries in the input have already been counted.
  • a value array that keeps track of the distinct numbers in the input array.
  • a count array that keeps track of how many times a number appears.

For example, after processing the 2 and the 4 in the input array, the array contents would be

input[] = { 2,4,6,7,7,4,4 };
used[]  = { 1,1,0,0,0,1,1 };  // all of the 2's and 4's have been used
value[] = { 2,4           };  // unique numbers found so far are 2 and 4
count[] = { 1,3           };  // one '2' and three '4's

Upvotes: 0

tdao
tdao

Reputation: 17668

Given the char array only contains '0' to '9', you may utilize a trivial lookup table like this:

#include <stdio.h>

typedef struct
{
    char c;
    int  num;
} TSet;

TSet my_set[] =
{
    { '0', 0 },
    { '1', 0 },
    { '2', 0 },
    { '3', 0 },
    { '4', 0 },
    { '5', 0 },
    { '6', 0 },
    { '7', 0 },
    { '8', 0 },
    { '9', 0 },
};

int main()
{
    char a[] = {'2','4','6','7','7', '4','4'};
    int i;
    for( i = 0; i < sizeof(a) / sizeof(char); i++ )
    {
        my_set[ a[i] - '0' ].num++;
    }

    printf( "%-10s%-10s\n", "Value:", "Count:" );
    for( i = 0; i < sizeof(my_set) / sizeof(TSet); i++ )
    {
        if( my_set[i].num != 0 )
        {
            printf( "%-10c%-10d\n", my_set[i].c, my_set[i].num );
        }
    }
}

Output:

Value:    Count:    
2         1         
4         3         
6         1         
7         2    

Upvotes: 1

Related Questions