5 методов Solidity, позволяющих проверить, содержит ли массив значение

Массивы — это важная структура данных в Solidity, языке, используемом для разработки смарт-контрактов в блокчейне Ethereum. Часто вам может потребоваться проверить, существует ли определенное значение в массиве. В этой записи блога мы рассмотрим пять различных методов выполнения этой задачи, используя разговорный язык и попутно предоставляя примеры кода.

Метод 1: линейный поиск
Самый простой способ проверить, содержит ли массив значение, — выполнить линейный поиск. Этот подход предполагает перебор каждого элемента массива и сравнение его с целевым значением. Если совпадение найдено, можно сделать вывод, что массив содержит искомое значение.

function linearSearch(uint[] memory arr, uint value) public pure returns (bool) {
    for (uint i = 0; i < arr.length; i++) {
        if (arr[i] == value) {
            return true;
        }
    }
    return false;
}

Метод 2: сопоставление
Другой подход заключается в использовании структуры данных сопоставления. В этом методе мы создаем сопоставление, где ключи представляют значения в массиве. Проверив, существует ли данный ключ в сопоставлении, мы можем определить, содержит ли массив желаемое значение.

function mappingSearch(uint[] memory arr, uint value) public pure returns (bool) {
    mapping(uint => bool) private valueExists;
    for (uint i = 0; i < arr.length; i++) {
        valueExists[arr[i]] = true;
    }
    return valueExists[value];
}

Метод 3: двоичный поиск (для отсортированных массивов)
Если массив отсортирован, мы можем использовать алгоритм двоичного поиска, чтобы эффективно проверить, содержит ли он значение. Бинарный поиск работает путем многократного деления пространства поиска пополам, пока целевое значение не будет найдено или не будет определено его отсутствие.

function binarySearch(uint[] memory arr, uint value) public pure returns (bool) {
    uint low = 0;
    uint high = arr.length - 1;

    while (low <= high) {
        uint mid = (low + high) / 2;

        if (arr[mid] == value) {
            return true;
        }
        if (arr[mid] < value) {
            low = mid + 1;
        } else {
            high = mid - 1;
        }
    }

    return false;
}

Метод 4: использование оператора «in» (Solidity 0.8.0 и выше)
В версии Solidity 0.8.0 и выше оператор «in» можно использовать для проверки наличия значения в массиве. Этот метод обеспечивает краткий и понятный способ выполнения проверки.

function inOperatorSearch(uint[] memory arr, uint value) public pure returns (bool) {
    return value in arr;
}

Метод 5: внешние библиотеки
Если вы предпочитаете более модульный подход, вы можете использовать внешние библиотеки, такие как EnumerableSet от OpenZeppelin, которые предоставляют встроенные функции для проверки того, содержит ли массив значение. Этот метод требует импорта библиотеки и использования ее функций.

import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
function externalLibrarySearch(uint[] memory arr, uint value) public pure returns (bool) {
    EnumerableSet.UintSet storage set = EnumerableSet.fromArray(arr);
    return EnumerableSet.contains(set, value);
}

В этой записи блога мы рассмотрели пять различных методов проверки наличия значения в массиве в Solidity. От простого линейного поиска до использования внешних библиотек — каждый метод имеет свои преимущества и ограничения. В зависимости от конкретных требований вашего смарт-контракта вы можете выбрать наиболее подходящий метод для вашего случая использования.