Si la declaración en el bucle for no filtra los elementos

 // @param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
    // @return _id - list of ids for homes
    function listHomesByAddress(string _physicalAddress) public returns(uint [] _id ) {
        uint [] results;
        for(uint i = 0 ; i<homes.length; i++) {
            if(keccak256(homes[i].physicalAddress) == keccak256(_physicalAddress) && homes[i].available == true) {
                results.push(homes[i].id);
            }
        }
        return results;

    }

Se supone que el resultado es una lista de identificaciones que coinciden con la dirección física ingresada; sin embargo, no se filtra, sino que devuelve todas las casas disponibles. Cuando cambio a usar String utils, nada cambia.

Aquí está el código completo:

pragma solidity ^0.4.0;

import "browser/StringUtils.sol";

// @title HomeListing

contract HomeListing {

struct Home {
    uint id;
    string physicalAddress;
    bool available;
}
Home[] public homes;
mapping (address => Home) hostToHome;
event HomeEvent(uint _id);
event Test(uint length);
constructor() {

}

// @param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
function addHome(string _physicalAddress) public {
    uint _id = uint(keccak256(_physicalAddress, msg.sender));
    homes.push(Home(_id, _physicalAddress, true));
}

// @param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
// @return _id - list of ids for homes
function listHomesByAddress(string _physicalAddress) public returns(uint [] _id ) {
    uint [] results;
    for(uint i = 0 ; i<homes.length; i++) {
        string location = homes[i].physicalAddress;
        if(StringUtils.equal(location,_physicalAddress )) {
            results.push(homes[i].id);
        }
    }
    return results;

    }
}
Decídete - ¿quieres returns(uint [] _id )o return results???
Un problema que tiene es que nunca inicializa uint [] results, por lo que comenzará a apuntar a la ranura de almacenamiento 0, que pertenece a Home[] public homes. Otro problema es que listHomesByAddressno está marcado como constanto viewy modificará tu contrato de almacenamiento.

Respuestas (1)

Su problema con la listHomesByAddressfunción es que está intentando crear una instancia de una matriz dinámica en la memoria, lo cual es imposible .

Dado que no sabe de antemano qué tamaño de matriz necesitará, deberá contarlo primero (lo que significa hacer un bucle dos veces, lo que es un desperdicio y costoso en términos de gas) o usar una matriz almacenada. Sin embargo, cuando se usa una matriz almacenada, cuesta gasolina limpiarla después, lo que también es un desperdicio.

En su lugar, podría usar una matriz de almacenamiento público para copiar ID, contando la cantidad de entradas encontradas a medida que avanza. Luego puede usar este contador como el índice de la última entrada relevante en la matriz de resultados. Ahora que sabemos la longitud de la matriz en la memoria que necesitamos, podemos continuar y crear la matriz final con las ID a través de una getArrayfunción:

uint[] public results;

function listHomesByAddress(string _physicalAddress) public returns(uint) {
    uint counter = 0;
    for(uint i = 0; i < homes.length; i++) {
        string location = homes[i].physicalAddress;
        if(StringUtils.equal(location, _physicalAddress)) {
            counter++;
            results[i] = homes[i].id;
        }
    }
    return getArray(counter);
}

function getArray(uint _length) public returns (uint[]) {
    uint[] memory arr = new uint[](_length);
    for (uint i = 0; i < _length; i++) {
        arr[i] = results[i];
    }
    return arr;
}

Si la matriz no es necesaria para un contrato inteligente y, en cambio, es para una DApp de front-end, simplemente puede devolver el contador y el front-end puede usarlo para recorrer la matriz de resultados para recopilar las ID correctas.