Tengo una matriz, algo como esto:

array =     
    [
        {
            "type": "apple",
            "color": "red",
            "id": "redApple"
        },
        {
            "type": "grape",
            "color": "green",
            "id": "greenGrape",
            "options": [
                {
                    "bunchName": "bunch1",
                    "size": "8"
                },
                {
                    "bunchName": "bunch2",
                    "size": "10"
                },
                {
                    "bunchName": "bunch3",
                    "size": "5"
                }
            ]
        }
    ]

Tengo una función que busca valores en la matriz.

function findValue (index, key) {
    return array[index][key];
}

var value = findValue(0, "id");
// returns redApple

¿Hay alguna manera de pasar un solo argumento a la función si quisiera encontrar algo más profundo en la matriz? Por ejemplo, si quisiera encontrar "bunchName" ¿podría pasarle algo así como 1, "options[0].bunchName" y volver "bunch1"?

Quiero una función que pueda manejar múltiples teclas. En mi proyecto real, a veces busco algo en el primer nivel, a veces busco en el segundo nivel, a veces en el tercer nivel, etc.

JQuery puede usarse si por alguna razón eso ayudara.

2
glass duo 29 oct. 2017 a las 19:13

4 respuestas

La mejor respuesta

Puede tomar la cadena, reemplazar los corchetes, dividir la cadena y reducir la ruta para el resultado. La función utiliza un objeto predeterminado para propiedades faltantes o no dadas.

function getValue(object, path) {
    return path
        .replace(/\[/g, '.')
        .replace(/\]/g, '')
        .split('.')
        .reduce(function (o, k) { return (o || {})[k]; }, object);
}

function findValue(index, path) {
    return getValue(array[index], path);
}

var array = [{ type: "apple", color: "red", id: "redApple" }, { type: "grape", color: "green", id: "greenGrape", options: [{ bunchName: "bunch1", size: "8" }, { bunchName: "bunch2", size: "10" }, { bunchName: "bunch3", size: "5" }] }];
        
console.log(findValue(1, "options[0].bunchName"));
3
Nina Scholz 29 oct. 2017 a las 17:04

Puede agregar una función que tome un objeto y una tecla y devuelva object[key] y luego divida su cadena de teclas en una lista de teclas individuales por el punto. Luego, puede recorrer la lista de teclas y usar la función para obtener el valor de cada nivel en su objeto:

Código totalmente no probado que acabo de preparar:

function valueByKey(obj, key) {
  if (obj) {
    return obj[key];
  }
}

function findValue(index, key) {
  const keys = key.split('.');
  let value = array[index];
  for (let i = 0; i < keys.length; i++) {
    value = valueByKey(value, keys[i]);
  }
  return value;
}
0
fiskeben 29 oct. 2017 a las 16:29

Solución no recurrente:

var array = [
    {
        'a': {
            'b': 1
        }
    }
];

function findValue(index, key) {
    var keys = key.split('.');
    var tmp = array[index];
    for (var i = 0; i < keys.length; i++) {
        if (!tmp.hasOwnProperty(keys[i]) || typeof tmp !== 'object') {
            // throw an exception, or return default value – property not found.
        }
        tmp = tmp[keys[i]];
    }

    return tmp;
}

findValue(0, 'a.b');
0
Ivan Kalita 29 oct. 2017 a las 16:31

Por lo que entiendo, salida de findValue (objeto, "bunchName"); debería ser "bunch3", donde el objeto es una matriz en el ejemplo de OP.

var object =
    [
        {
            "type": "apple",
            "color": "red",
            "id": "redApple"
        },
        {
            "type": "grape",
            "color": "green",
            "id": "greenGrape",
            "options": [
                {
                    "bunchName": "bunch1",
                    "size": "8"
                },
                {
                    "bunchName": "bunch2",
                    "size": "10"
                },
                {
                    "bunchName": "bunch3",
                    "size": "5"
                }
            ]
        }
    ]

var findValue = (object, key) => {
    var resultValue;
    var rec = (currentObj) => {
        if(currentObj && typeof currentObj === "object"){
            for(let curKey in currentObj){
                if (curKey === key){
                    resultValue = currentObj[curKey];
                }else{
                    rec(currentObj[curKey]);
                }
            }
        }

    }
    rec(object);
    return resultValue;
}
console.log(findValue(object, "bunchName"));
0
Shishir Arora 29 oct. 2017 a las 16:28