2

I have an array, something like this:

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"
                }
            ]
        }
    ]

I have a function that searches for values in the array.

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

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

Is there a way I could pass a single argument to the function if I wanted to find something deeper in the array? For example, if I wanted to find "bunchName" could I pass it something like 1, "options[0].bunchName" and get back "bunch1"?

I want a function that can handle multiple keys. In my real project sometimes I'm looking for something on the first level, sometimes I'm looking on the second level, sometimes the third level, etc.

jQuery can be used if for some reason that would help.

5
  • 1
    please specify the wanted result by taking a path to an object with an array with objects. Commented Oct 29, 2017 at 16:16
  • I don't understand your comment. Commented Oct 29, 2017 at 16:22
  • Probably want to use a library like lodash to simplify this Commented Oct 29, 2017 at 16:25
  • 1
    please add the result if taken 'options.bunchName' as parameter for the function. Commented Oct 29, 2017 at 16:27
  • Some libraries like Lodash can be used lodash.com/docs/4.17.4#get. Otherwise, it can be done in JavaScript with recursion, loop, or maybe eval Commented Oct 29, 2017 at 16:30

4 Answers 4

3

You could take the string, replace the brackets, split the string and reduce the path for the result. The function uses a default object for missing or not given properties.

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"));

Sign up to request clarification or add additional context in comments.

1 Comment

This was a good answer. The only issue I had with it was that I do not want to use .reduce because of compatibility issues with older versions of IE. But I was able to use this with a work around for the reduce portion of the code. Thanks.
0

From what I understand, output of findValue(object, "bunchName"); should be "bunch3", where object is array in OP's example.

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"));

Comments

0

You could add a function that takes an object and a key and returns object[key] and then split your key string into a list of individual keys by the dot. Then you could traverse the list of keys and use the function to get the value for each level in your object:

Totally untested code I just whipped up:

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;
}

Comments

0

Non-recurrent solution:

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');

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.