Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get values by property name from an object at different levels

I have an object in the below format and I need to get all values from the Price property at all levels of the object.

var o = {
    Id: 1,
    Price: 10,
    Attribute: {
        Id: 1,
        Price: 2,
        Modifier: {
            Id: 34,
            Price: 33
        }
    }
};

I was thinking of LinqToJS and jquery.map() methods but I'd like to get a method as generic as possible. I tried this but it only works at the first level:

var keys = $.map(o, function(value, key) {
    if (key == "Price") {
        return value;
    }
});
like image 990
Diego Fuks Avatar asked Mar 19 '16 20:03

Diego Fuks


2 Answers

You can use a recursive function which tests the type of name of the property and its type. If it's name is Price, add it to an array. If it's an object, recurse through that object to find a Price key. Try this:

function getPrices(obj, arr) {
    $.each(obj, function(k, v) {
        if (k == "Price")
            arr.push(v);
        else if (typeof(v) == 'object')
            getPrices(obj[k], arr);
    });
    return arr;
}

var prices = getPrices(o, []);
console.log(prices); // = [10, 2, 33]

Working example

like image 198
Rory McCrossan Avatar answered Oct 28 '22 14:10

Rory McCrossan


You can use jQuery's $.map() to do this very easily:

var o = {
  Id: 1,
  Price: 10,
  Attribute: {
    Id: 1,
    Price: 2,
    Modifier: {
      Id: 34,
      Price: 33
    }
  }
};


var res = $.map(o, function mapper(obj, key) {
  return key === "Price" ? obj : $.map(obj, mapper)
});


document.querySelector("pre").textContent = JSON.stringify(res)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<pre></pre>

This works because of the odd feature jQuery's $.map has where if you return an Array from the callback, it gets flattened into the result.

Therefore we can recursively call $.map with the same function on anything that's not the Price key, and the array it returns will just get emptied into the final result.

You can avoid some calls if you check typeof obj === "object" if you wish.

like image 33
user1106925 Avatar answered Oct 28 '22 14:10

user1106925