admin管理员组

文章数量:1335624

I'm new to JavaScript and I'm really lost here. Here is some data produced by PHP json_encode() (and limited to most pertinent keys) :

[
  {
    "product_option_id":"229",
    "product_option_value":
    [
      {
        "product_option_value_id":"21",
        "option_value_id":"51",
        "price":"1,22 €",
        "price_prefix":"+"
      },
      {
        "product_option_value_id":"22",
        "option_value_id":"52",
        "price":false,
        "price_prefix":"+"
      },
      {
        "product_option_value_id":"23",
        "option_value_id":"53",
        "price":"2,42 €",
        "price_prefix":"+"
      }
    ],
    "option_id":"14",
    "type":"radio",
    "value":""
  },
  {
    "product_option_id":"228",
    "product_option_value":
    [
      {
        "product_option_value_id":"19",
        "option_value_id":"49",
        "price":"1,22 €",
        "price_prefix":"+"
      },
      {
        "product_option_value_id":"20",
        "option_value_id":"50",
        "price":"2,42 €",
        "price_prefix":"+"
      }
    ],
    "option_id":"13",
    "type":"select",
    "value":""
  }
]

I need to access price and price_prefix values (in JavaScript) knowing product_option_id and product_option_value_id.

How do I do that ? Should I go for a loop ?

Update :

Thanks for replies. Unless I missed something, it appears that in my case arrays (as ugly as they may be…) are much more efficient than all the proposed solutions (I'll try another approach, formatting a JSON object corresponding to my needs with PHP rather than using the "default" one, but it's off topic here). Though I'm not fond of adding libraries and it's a bit slower than most other solutions, I'll accept Matt's solution because it really seems to make life easier as far as JSON access is concerned. But it should be noted that Yeldard and Barmar's (almost cloned) solutions are faster than other propositions.

I'm new to JavaScript and I'm really lost here. Here is some data produced by PHP json_encode() (and limited to most pertinent keys) :

[
  {
    "product_option_id":"229",
    "product_option_value":
    [
      {
        "product_option_value_id":"21",
        "option_value_id":"51",
        "price":"1,22 €",
        "price_prefix":"+"
      },
      {
        "product_option_value_id":"22",
        "option_value_id":"52",
        "price":false,
        "price_prefix":"+"
      },
      {
        "product_option_value_id":"23",
        "option_value_id":"53",
        "price":"2,42 €",
        "price_prefix":"+"
      }
    ],
    "option_id":"14",
    "type":"radio",
    "value":""
  },
  {
    "product_option_id":"228",
    "product_option_value":
    [
      {
        "product_option_value_id":"19",
        "option_value_id":"49",
        "price":"1,22 €",
        "price_prefix":"+"
      },
      {
        "product_option_value_id":"20",
        "option_value_id":"50",
        "price":"2,42 €",
        "price_prefix":"+"
      }
    ],
    "option_id":"13",
    "type":"select",
    "value":""
  }
]

I need to access price and price_prefix values (in JavaScript) knowing product_option_id and product_option_value_id.

How do I do that ? Should I go for a loop ?

Update :

Thanks for replies. Unless I missed something, it appears that in my case arrays (as ugly as they may be…) are much more efficient than all the proposed solutions (I'll try another approach, formatting a JSON object corresponding to my needs with PHP rather than using the "default" one, but it's off topic here). Though I'm not fond of adding libraries and it's a bit slower than most other solutions, I'll accept Matt's solution because it really seems to make life easier as far as JSON access is concerned. But it should be noted that Yeldard and Barmar's (almost cloned) solutions are faster than other propositions.

Share Improve this question edited Apr 13, 2017 at 12:40 CommunityBot 11 silver badge asked Aug 12, 2015 at 9:40 Skippy le Grand GourouSkippy le Grand Gourou 7,7346 gold badges64 silver badges81 bronze badges 6
  • What have you already tried? Did you try a loop? – Andy Commented Aug 12, 2015 at 9:43
  • You have to use nested loops. – Barmar Commented Aug 12, 2015 at 9:45
  • @Andy : Actually the question is more "what is the most efficient way to do that ?" — I know how to loop. I rephrased before to publish thinking it might be off topic otherwise, and lost the meaning, sorry. – Skippy le Grand Gourou Commented Aug 12, 2015 at 9:47
  • Also, I found Access / process (nested) objects, arrays or JSON just after posting of course. I'm reading, it, it does help (I considered deleting my question) but for now I don't see anything about access by value. – Skippy le Grand Gourou Commented Aug 12, 2015 at 9:49
  • Out of interest, what's the purpose of testing the prepocessed array values (ABC) in the perf tests? Is that the format you are going to look at creating in PHP? – Matt Commented Aug 13, 2015 at 19:50
 |  Show 1 more ment

7 Answers 7

Reset to default 2

lodash would make this easier and neater. It provides _.find or _.filter depending on if your id's are unique or not.

var record = _.find( data_structure, {
  "product_option_id": "229"
})
if ( !record ) throw new Error("Record not found");

var value = _.find( record.product_option_value, {
  "product_option_value_id":"22" 
})
if ( !value ) throw new Error("Value not found");

console.log( "price[%s] prefix[%s]", value.price, value.price_prefix )

Demo

For more plex data selection, you might want to look at sift.js. It's based on mongodb's query system.

var records = sift({ 
    "product_option_id": "229", 
    "product_option_value": {
      $elemMatch: {
        "product_option_value_id": "22"  
      }
    }
  },
  data_structure
)

you can do like this

    for(var i in jsonData) {
    var item = jsonData[i];
    if(item.product_option_id == 229) {
        for(var j in item.product_option_value){
            var item1 = item.product_option_value[j];
            if(item1.product_option_value_id == 21) {
                //your item here
                break;
            }
        }
       break;
    }

}

This should do it:

var productOptionId = 229;
var productOptionValue = 22;

var matchingOuter = yourData.filter(function(i){
    return i.product_option_id === productOptionId; 
})[0];

if (matchingOuter) {
    var matchingInner = matchingOuter.product_option_value.filter(function(i){
        return i.product_option_value === productOptionValue;
    })[0];
}  

If a matching item exists it will be assigned to matchingInner

Following would do:

function getProductValues(products, product_option_id, product_option_value_id) {
    if (!product_option_id || !product_option_value_id) {
        return;
    }

    return products.filter(function(product) {
        return +product.product_option_id === product_option_id;
    }).map(function (product) {
        var option_values = product.product_option_value;
        return option_values.filter(function (option) {
            return +option.option_value_id === product_option_value_id;
        })[0] || [];
    })[0] || [];
}

Usage:

getProductValues(data, 229, 51)

Result:

{product_option_value_id: "21", option_value_id: "51", price: "1,22 €", price_prefix: "+"}

Use filter on the main array to grab the right object, filter again on the option_value_id, then map on the returned array to get a single price/prefix object. map and filter both return arrays which is why you see the code picking up the first element ([0]) in a couple of places.

function getData(data, options) {
    return data.filter(function (product) {
      return product.product_option_id === options.id;
    })[0].product_option_value.filter(function (details) {
       return details.product_option_value_id === options.optionId;
    }).map(function(el) {
      return { price: el.price, prefix: el.price_prefix }
    })[0];
}

getData(data, { id: '229', optionId: '23' }); // { price: "2,42 €", prefix: "+" }

DEMO

Use nested loops to search through the main array and the sub-arrays, looking for the matching element.

function find_product(product_option_id, product_option_value_id) {
    for (var i = 0; i < products.length; i++) {
        var product = products[i];
        if (product.product_option_id == product_option_id) {
            for (var j = 0; j < product.product_option_value.length; j++) {
                var value = product.product_option_value[j];
                if (value.product_option_value_id == product_option_value_id) {
                    return { price: value.price, price_prefix: value.price_prefix }
                }
            }
        }
    }
}

Yes, you need to enumerate through the array and find your items:

Here is the working code which outputs price_prefix and price of product with product_option_id = 228 and product_option_value_id = 19. You can replace these values with your own.

for (var i = 0; i < obj.length; i++) // Enumerate through array
{
    var item = obj[i];
    if (item.product_option_id === "228") // Filtering items by product_option_id
    {
        // When necessary product_option_id found
        for (var j = 0; j < item.product_option_value.length; j++) // Enumerate through its products
        {
            var productItem = item.product_option_value[j]; 
            if (productItem.product_option_value_id === "19") // Filtering by product_option_value_id
            {
                // here it is. productItem is found! do whatever you want with it
                alert(productItem.price_prefix + " " + productItem.price);
            }
        }
    }
}

Working JSFiddle demo.

本文标签: javascriptAccess by value on nested JSON arraysStack Overflow