Solidity / Array

Array

Array бол нэг төрлийн утгуудыг дараалсан байдлаар хадгалах өгөгдлийн бүтэц. Solidity-д array хоёр хэлбэртэй — тогтмол урт (fixed-size) ба динамик урт (dynamic).

Fixed-size array — тогтмол урт

Урт нь урьдчилан тодорхойлогдсон, өөрчлөгдөхгүй array:

solidity
uint256[5]  public scores;         // яг 5 элемент
address[3]  public winners;        // яг 3 элемент
bool[10]    public slots;          // яг 10 элемент

Зарлах үед бүх элемент default утга авна — uint256 бол 0, bool бол false, address бол address(0).

solidity
contract FixedArray {
    uint256[3] public rgb;

    function setColor(uint256 r, uint256 g, uint256 b) public {
        rgb[0] = r;
        rgb[1] = g;
        rgb[2] = b;
    }

    function getRed() public view returns (uint256) {
        return rgb[0];
    }
}

Хил хэтэрсэн index ашиглахад runtime revert гарна:

solidity
uint256[3] arr;
arr[5] = 1;   // ❌ index out of bounds → revert

Dynamic array — динамик урт

Урт нь өсч буурдаг array. Storage-д зарлахад хэмжээний хязгааргүй:

solidity
uint256[] public numbers;
address[] public members;
string[]  public names;

push — элемент нэмэх

solidity
contract DynamicArray {
    uint256[] public numbers;

    function addNumber(uint256 n) public {
        numbers.push(n);   // array-ийн төгсгөлд нэмнэ
    }

    function getLength() public view returns (uint256) {
        return numbers.length;
    }

    function getLast() public view returns (uint256) {
        require(numbers.length > 0, "Array хоосон байна");
        return numbers[numbers.length - 1];
    }
}

pop — сүүлийн элемент хасах

solidity
function removeLast() public {
    require(numbers.length > 0, "Array хоосон байна");
    numbers.pop();   // сүүлийн элементийг устгана, length-г нэгээр багасгана
}

pop нь хасагдсан утгыг буцааж өгдөггүй — устгахаас өмнө хадгалах шаардлагатай бол:

solidity
function popAndReturn() public returns (uint256 last) {
    last = numbers[numbers.length - 1];   // эхлэж хадгална
    numbers.pop();                         // дараа нь устгана
}

Array iterate хийх

solidity
contract Scores {
    uint256[] public scores;

    function addScore(uint256 s) public { scores.push(s); }

    function getTotal() public view returns (uint256 total) {
        for (uint256 i = 0; i < scores.length; i++) {
            total += scores[i];
        }
    }

    function getAverage() public view returns (uint256) {
        require(scores.length > 0, "Оноо байхгүй");
        return getTotal() / scores.length;
    }

    function findMax() public view returns (uint256 max) {
        for (uint256 i = 0; i < scores.length; i++) {
            if (scores[i] > max) {
                max = scores[i];
            }
        }
    }
}

⚠️ Gas анхааруулга: Array урт ихсэх тусам loop-ийн gas зарцуулалт нэмэгдэнэ. Маш урт array-г бүтнээр нь давтах нь gas limit-г давж revert болох эрсдэлтэй.

Storage vs Memory array

Storage array — blockchain-д байнга хадгалагдана, state variable.

Memory array — функц дотор түр үүснэ, функц дуусмагц устана. Урт нь урьдчилан тодорхойлогдсон байх ёстой.

solidity
contract ArrayLocation {
    uint256[] public stored;   // storage array

    function processNumbers(uint256 count) public view returns (uint256[] memory) {
        // memory array — тогтмол урттайгаар үүсгэнэ
        uint256[] memory result = new uint256[](count);

        for (uint256 i = 0; i < count; i++) {
            result[i] = (i + 1) * 10;
        }

        return result;   // memory array буцаана
    }
}

Memory array-д push/pop ажилладаггүй — зөвхөн index-ээр унших, бичих боломжтой.

Storage-г memory-д хуулах — gas оновчлол

solidity
uint256[] public bigArray;

// ❌ storage-г дахин дахин уншина → gas өндөр
function sumExpensive() public view returns (uint256 total) {
    for (uint256 i = 0; i < bigArray.length; i++) {
        total += bigArray[i];   // SLOAD бүр gas зарцуулна
    }
}

// ✅ нэг удаа memory-д хуулна → gas хямд
function sumCheap() public view returns (uint256 total) {
    uint256[] memory arr = bigArray;   // нэг удаа хуулна
    for (uint256 i = 0; i < arr.length; i++) {
        total += arr[i];
    }
}

Array delete-ийн аюул

delete arr[i] нь элементийг default утга болгодог, array-г богиносгодоггүй:

solidity
uint256[] public nums = [10, 20, 30, 40, 50];

delete nums[2];
// nums → [10, 20, 0, 40, 50]  — length өөрчлөгдсөнгүй!
// 0 "хоосон цоорхой" болж үлдэнэ

Дунд элементийг зайлуулж array-г нягтруулахын тулд:

solidity
// Арга 1: Сүүлийн элементтэй сольж pop хийх (дараалал алдагдана)
function removeAt(uint256 index) public {
    require(index < numbers.length, "Буруу index");
    numbers[index] = numbers[numbers.length - 1];   // сүүлийнхийг хийнэ
    numbers.pop();                                   // сүүлийнхийг устгана
}

// Арга 2: Дараалал хадгалах (gas өндөр)
function removeAtOrdered(uint256 index) public {
    require(index < numbers.length, "Буруу index");
    for (uint256 i = index; i < numbers.length - 1; i++) {
        numbers[i] = numbers[i + 1];   // зүүн тийш шилжүүлнэ
    }
    numbers.pop();
}

2D array

solidity
uint256[3][3] public grid;   // 3×3 тогтмол
uint256[][]   public matrix; // динамик

function setCell(uint256 row, uint256 col, uint256 val) public {
    grid[row][col] = val;
}

Дараагийн хичээлд:

struct — холбоотой өгөгдлийг нэг нэгжид бүлэглэх, mapping ба array-тай хослуулах аргыг судална.