简体   繁体   中英

How to calculate the average of JArray value items

I have the following JArray object:

entry: [
    {
        "name": "reading1",
        "value": 9.194
    },
    {
        "name": "reading2",
        "value": 9.527
    },
    {
        "name": "reading3",
        "value": 10.194
    },
    {
        "name": "reading4",
        "value": 10.944
    }
]

I would like to return whole values and calculate the average of them.

I tried to loop over the JArray and return whole value items like this: 9.194 9.527, 10.194, 10.944 . But I cannot create a list from value items to can calculate average of them.

foreach (JObject item in entry.Children<JObject>())
{
    foreach (JProperty prop in item.Properties())
    {
        if (prop.Name.Equals("value"))
        {
            List<string> values = new List<string>();
            values.Add((string)prop.Value); //just add one value
            for (int i = 0; i < values.Count; i++)
            {
                sum += decimal.Parse(values[i]);
            }
            average = sum / 4;
        }
    }
}

I Cannot create a list of whole value items. list values just returns the last value.

The issue is where you're creating your list and calculating your average. Think about how you get a mean value with a calculator:

  1. You get a list of numbers.
  2. You add each number into the calculator to get the total.
  3. You divide by the total by the number of items you added together.

What your code is doing:

  1. It goes through each number in the array.
  2. Make a list of 1 number.
  3. Add each number in step 2 together (you only have one number)
  4. Divide that by 4 (for some reason)?
  5. Repeat from 2. for each number in 1.

I'm sure you can see why you're having problems. Remember that computers will do exactly what you tell them. Nothing more. Nothing less.

You need to rewrite it like this:

List<string> values = new List<string>(); // build list outside of the loop so that we collect all of the values
foreach (JObject item in entry.Children<JObject>())
{
    foreach (JProperty prop in item.Properties())
    {
        if (prop.Name.Equals("value"))
        {
            values.Add((string)prop.Value);
        }
    }
}

for (int i = 0; i < values.Count; i++)
{
    sum += decimal.Parse(values[i]); // calculate the total
}
average = sum / values.Count; // calculate the average

It's worth noting that you can simply do prop.Value.Value<decimal>() as opposed to converting it to a decimal afterwards. Then you just need a List<decimal> , not a List<string> .

Or, perhaps more simply, using LINQ:

var average = entry.Children<JObject>()
    .Where(c => c.ContainsKey("value")) // only consider children that contain "value" to avoid errors
    .Select(c => c["value"].Value<decimal>()) // select the decimal value of "value"
    .DefaultIfEmpty() // don't throw an error for an empty list
    .Average(); // calculate the average

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM