Apply #71: Add ArrayUnique() function.
This commit is contained in:
parent
c4121d2dba
commit
c4ef6d4ddc
2 changed files with 64 additions and 6 deletions
43
src/Array.c
43
src/Array.c
|
@ -274,6 +274,49 @@ ArraySort(Array * array, int (*compare) (void *, void *))
|
||||||
ArrayQuickSort(array, 0, array->size - 1, compare);
|
ArrayQuickSort(array, 0, array->size - 1, compare);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Array *
|
||||||
|
ArrayUnique(Array * array, int (*compare) (void *, void *))
|
||||||
|
{
|
||||||
|
Array *ret;
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!array)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ArrayDuplicate(array);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ArraySize(ret) == 1)
|
||||||
|
{
|
||||||
|
/* There can't be any duplicates when there's only 1 value */
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArraySort(ret, compare);
|
||||||
|
|
||||||
|
for (i = 1; i < ArraySize(ret); i++)
|
||||||
|
{
|
||||||
|
void *cur = ret->entries[i];
|
||||||
|
void *prev = ret->entries[i - 1];
|
||||||
|
|
||||||
|
if (compare(cur, prev) == 0)
|
||||||
|
{
|
||||||
|
/* Remove the duplicate, and put i back where it was. */
|
||||||
|
ArrayDelete(ret, i--);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayTrim(ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Even though the following operations could be done using only the
|
/* Even though the following operations could be done using only the
|
||||||
* public Array API defined above, I opted for low-level struct
|
* public Array API defined above, I opted for low-level struct
|
||||||
* manipulation because it allows much more efficient copying; we only
|
* manipulation because it allows much more efficient copying; we only
|
||||||
|
|
|
@ -64,7 +64,7 @@ typedef struct Array Array;
|
||||||
* used with the other functions in this API, or NULL if there was an
|
* used with the other functions in this API, or NULL if there was an
|
||||||
* error allocating memory for the array.
|
* error allocating memory for the array.
|
||||||
*/
|
*/
|
||||||
extern Array * ArrayCreate(void);
|
extern Array *ArrayCreate(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deallocate an array. Note that this function does not free any of
|
* Deallocate an array. Note that this function does not free any of
|
||||||
|
@ -88,7 +88,7 @@ extern size_t ArraySize(Array *);
|
||||||
* or
|
* or
|
||||||
* .Fn ArraySet .
|
* .Fn ArraySet .
|
||||||
*/
|
*/
|
||||||
extern void * ArrayGet(Array *, size_t);
|
extern void *ArrayGet(Array *, size_t);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert the specified element at the specified index in the specified
|
* Insert the specified element at the specified index in the specified
|
||||||
|
@ -105,7 +105,7 @@ extern int ArrayInsert(Array *, size_t, void *);
|
||||||
* specified value. This function will return the old value at that
|
* specified value. This function will return the old value at that
|
||||||
* index, if any.
|
* index, if any.
|
||||||
*/
|
*/
|
||||||
extern void * ArraySet(Array *, size_t, void *);
|
extern void *ArraySet(Array *, size_t, void *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append the specified element to the end of the specified array. This
|
* Append the specified element to the end of the specified array. This
|
||||||
|
@ -121,7 +121,7 @@ extern int ArrayAdd(Array *, void *);
|
||||||
* Remove the element at the specified index from the specified array.
|
* Remove the element at the specified index from the specified array.
|
||||||
* This function returns the element removed, if any.
|
* This function returns the element removed, if any.
|
||||||
*/
|
*/
|
||||||
extern void * ArrayDelete(Array *, size_t);
|
extern void *ArrayDelete(Array *, size_t);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort the specified array using the specified sort function. The
|
* Sort the specified array using the specified sort function. The
|
||||||
|
@ -136,6 +136,21 @@ extern void * ArrayDelete(Array *, size_t);
|
||||||
*/
|
*/
|
||||||
extern void ArraySort(Array *, int (*) (void *, void *));
|
extern void ArraySort(Array *, int (*) (void *, void *));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all duplicates from an array by using the given comparison
|
||||||
|
* function to sort the array, then remove matching values. This
|
||||||
|
* function returns a new array with all duplicates removed. The
|
||||||
|
* original array is unaffected. Note that arrays only store pointers
|
||||||
|
* to values, usually values on the heap. Thus, it is possible to lose
|
||||||
|
* pointers to duplicate values and have them leak.
|
||||||
|
* .P
|
||||||
|
* This is a relatively expensive operation. The array must first be
|
||||||
|
* duplicated. Then it is sorted, then it is iterated from beginning
|
||||||
|
* to end to remove duplicate entires. Note that the comparison
|
||||||
|
* function is executed on each element at least twice.
|
||||||
|
*/
|
||||||
|
extern Array *ArrayUnique(Array *, int (*) (void *, void *));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If possible, reduce the amount of memory allocated to this array
|
* If possible, reduce the amount of memory allocated to this array
|
||||||
* by calling
|
* by calling
|
||||||
|
@ -152,13 +167,13 @@ extern int ArrayTrim(Array *);
|
||||||
* .Fn va_arg
|
* .Fn va_arg
|
||||||
* and friends.
|
* and friends.
|
||||||
*/
|
*/
|
||||||
extern Array * ArrayFromVarArgs(size_t, va_list);
|
extern Array *ArrayFromVarArgs(size_t, va_list);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Duplicate an existing array. Note that arrays only hold pointers to
|
* Duplicate an existing array. Note that arrays only hold pointers to
|
||||||
* their data, not the data itself, so the duplicated array will point
|
* their data, not the data itself, so the duplicated array will point
|
||||||
* to the same places in memory as the original array.
|
* to the same places in memory as the original array.
|
||||||
*/
|
*/
|
||||||
extern Array * ArrayDuplicate(Array *);
|
extern Array *ArrayDuplicate(Array *);
|
||||||
|
|
||||||
#endif /* CYTOPLASM_ARRAY_H */
|
#endif /* CYTOPLASM_ARRAY_H */
|
||||||
|
|
Loading…
Reference in a new issue