Blockchain/Solidity

delete element of array and mapping - 공부하는 도비

DOVISH WISDOM 2023. 1. 2. 20:30
728x90
반응형

array의 인덱스 번호로 element 삭제 방법

pragma solidity ^0.8.1;

contract Practice {
    uint256[] private arr;

    function remove(uint256 _index) private {
        require(_index < arr.length, "index out of bound");

        for (uint i = _index; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];
        }
        arr.pop();
    }

    function test() external {
        // case_1
        arr = [1, 2, 3, 4, 5];
        remove(2); // want : arr = [1, 2, 4, 5]

        // checking
        assert(arr[0] == 1);
        assert(arr[1] == 2);
        assert(arr[2] == 4);
        assert(arr[3] == 5);
        assert(arr.length == 4);

        // case_2
        arr = [1];
        remove(0); // want : arr = []

        // checking
        assert(arr.length == 0);
    }
}

 

 

mapping의 value리스트 값 삭제하는 방법 (이중 리스트의 값 삭제와 동일)

pragma solidity ^0.8.7;

contract Test {
    address public owner;
    mapping (uint256 => address) public tokenOwner; // 특정 토큰의 번호를 넣었을 때, 그 토큰의 소유주를 출력 
    mapping (uint256 => string) public tokenStrs;   // 특정 토큰에 적혀있는 Str 출력 
    mapping (address => uint256[]) private ownedTokens;    // 소유한 토큰 리스트 : 주소를 입력하면, 그 주소가 가진 tokenId를 출력력

    constructor() public {
        owner = msg.sender;
    }
    // 토큰 발행 함수
    function mintWithTokenURI(address to, uint256 tokenId, string memory tokenStr) public {
        require(owner == msg.sender);

        // to에게 tokenId를 발행
        tokenOwner[tokenId] = to;
        tokenStrs[tokenId] = tokenStr;

        // add token to the list 
        ownedTokens[to].push(tokenId);
    }

    // 토큰 전송 (from address to address sometokenid)
    function transferFromTo(address from, address to, uint256 tokenId) public {
        require(owner == msg.sender);
        require(from == tokenOwner[tokenId], "you are not the owner of the token");
        tokenOwner[tokenId] = to;

        // from 주소에 해당하는 tokenId를 list에서 삭제해야함 
        // if문으로 tokenId에 해당하는 index를 얻고, 그 값을 삭제
        for(uint256 i = 0; i < ownedTokens[from].length; i++) {
            if (ownedTokens[from][i] == tokenId) {
                ownedTokens[from][i] = ownedTokens[from][ownedTokens[from].length-1];    
                ownedTokens[from].pop();
                break;
            }
        }
        // 새로운 주소에 add token to the list
        ownedTokens[to].push(tokenId);
    } 
    // 소유한 토큰
    function PrintOwnedTokens(address some_address) public view returns (uint256[] memory) {
        return ownedTokens[some_address];
    }
}

 

이 부분이 삭제에 해당하는 부분입니다. 

 // from 주소에 해당하는 tokenId를 list에서 삭제해야함 
        // if문으로 tokenId에 해당하는 index를 얻고, 그 값을 삭제
        
        for(uint256 i = 0; i < ownedTokens[from].length; i++) {
            if (ownedTokens[from][i] == tokenId) {
                ownedTokens[from][i] = ownedTokens[from][ownedTokens[from].length-1];    
                ownedTokens[from].pop();
                break;
            }
        }

 

물론 함수로도 작성이 가능합니다.

        //_removeTokenId(from, tokenId); 
        
    // private으로 선언
    function _removeTokenId(address from, uint256 tokenId) private { 
        for(uint256 i = 0; i < ownedTokens[from].length; i++) {
            if (ownedTokens[from][i] == tokenId) {
                ownedTokens[from][i] = ownedTokens[from][ownedTokens[from].length-1];    
                ownedTokens[from].pop();
                break;
            }
        }
    }

 

 

솔리디티에서 배열의 값을 삭제하기 위해선 아래 그림과 같은 과정을 거쳐야 합니다. 

arr = [10, 40, 5, 8, 20, 15] 

40을 삭제하고 싶다면, 

40과 배열의 맨 끝 값(15)과 자리를 바꿉니다(swap).

마지막으로 arr.pop()으로 배열의 마지막 값을 삭제(꺼냅니다(pop))합니다.