Skip to content

Commit e57bd0e

Browse files
sivaratrisrinivasSrinivas Sivaratri
and
Srinivas Sivaratri
committed
Add Array.uniquifySorted to the Arrays library
This adds a uniquifySorted function to remove duplicates from sorted arrays. The function has O(n) time complexity and works with uint256, address, and bytes32 array types. This is particularly useful when mappings cannot be utilized, and provides an easy way to combine Array.sort() + Array.uniquifySorted(). Fixes OpenZeppelin#5520 Co-Authored-By: Srinivas Sivaratri <[email protected]>
1 parent 506e1f8 commit e57bd0e

File tree

6 files changed

+345
-272
lines changed

6 files changed

+345
-272
lines changed

contracts/mocks/ArraysMock.sol

+12
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ contract Uint256ArraysMock {
5656
function length() external view returns (uint256) {
5757
return _array.length;
5858
}
59+
60+
function uniquifySorted(uint256[] memory array) external pure returns (uint256[] memory) {
61+
return array.uniquifySorted();
62+
}
5963
}
6064

6165
contract AddressArraysMock {
@@ -90,6 +94,10 @@ contract AddressArraysMock {
9094
function length() external view returns (uint256) {
9195
return _array.length;
9296
}
97+
98+
function uniquifySorted(address[] memory array) external pure returns (address[] memory) {
99+
return array.uniquifySorted();
100+
}
93101
}
94102

95103
contract Bytes32ArraysMock {
@@ -124,4 +132,8 @@ contract Bytes32ArraysMock {
124132
function length() external view returns (uint256) {
125133
return _array.length;
126134
}
135+
136+
function uniquifySorted(bytes32[] memory array) external pure returns (bytes32[] memory) {
137+
return array.uniquifySorted();
138+
}
127139
}

contracts/utils/Arrays.sol

+65
Original file line numberDiff line numberDiff line change
@@ -479,4 +479,69 @@ library Arrays {
479479
sstore(array.slot, len)
480480
}
481481
}
482+
483+
/**
484+
* @dev Removes duplicate values from a sorted array. This function does not check that the array is sorted,
485+
* behavior is undefined if the array is not sorted. The resulting array will have no duplicates and will
486+
* be shorter or the same length as the input array.
487+
*
488+
* This operation is performed in-place by moving elements and modifying the length of the array.
489+
* Time complexity O(n).
490+
*
491+
* WARNING: This function is destructive. It will modify the array passed by reference.
492+
*/
493+
function uniquifySorted(uint256[] memory array) internal pure returns (uint256[] memory) {
494+
if (array.length <= 1) {
495+
return array;
496+
}
497+
498+
uint256 resultSize = 1;
499+
for (uint256 i = 1; i < array.length; ++i) {
500+
if (array[i] != array[i - 1]) {
501+
if (i != resultSize) {
502+
array[resultSize] = array[i];
503+
}
504+
++resultSize;
505+
}
506+
}
507+
508+
// Resize the array by creating a new one (can't modify length of memory arrays directly)
509+
uint256[] memory result = new uint256[](resultSize);
510+
for (uint256 i = 0; i < resultSize; ++i) {
511+
result[i] = array[i];
512+
}
513+
return result;
514+
}
515+
516+
/**
517+
* @dev Removes duplicate values from a sorted address array. This function does not check that the array
518+
* is sorted, behavior is undefined if the array is not sorted. The resulting array will have no duplicates
519+
* and will be shorter or the same length as the input array.
520+
*
521+
* This operation is performed in-place by moving elements and modifying the length of the array.
522+
* Time complexity O(n).
523+
*
524+
* WARNING: This function is destructive. It will modify the array passed by reference.
525+
*/
526+
function uniquifySorted(address[] memory array) internal pure returns (address[] memory) {
527+
uint256[] memory castedArray = _castToUint256Array(array);
528+
uniquifySorted(castedArray);
529+
return array;
530+
}
531+
532+
/**
533+
* @dev Removes duplicate values from a sorted bytes32 array. This function does not check that the array
534+
* is sorted, behavior is undefined if the array is not sorted. The resulting array will have no duplicates
535+
* and will be shorter or the same length as the input array.
536+
*
537+
* This operation is performed in-place by moving elements and modifying the length of the array.
538+
* Time complexity O(n).
539+
*
540+
* WARNING: This function is destructive. It will modify the array passed by reference.
541+
*/
542+
function uniquifySorted(bytes32[] memory array) internal pure returns (bytes32[] memory) {
543+
uint256[] memory castedArray = _castToUint256Array(array);
544+
uniquifySorted(castedArray);
545+
return array;
546+
}
482547
}

0 commit comments

Comments
 (0)