muhammad
muhammad

Reputation: 255

How to count and add the values of keys in a object

I need to write a function that takes in 2 arguments, the first argument is a list of <li> elements and the second argument is an object. The object is list of products and their prices. All the <li>elements will have text containing a name of a product.The function should check the price of each product mentioned, calculate and return the total price.

Example:

<ul>
    <li>oreos<li/>
    <li>milk<li/>
<ul/>
let products = {
    oreos: 20,
    milk:  17,
    bread: 12,
    doritos: 10
}

I have tried using a for in/of loop to go through the products object and match it to the <li> using .innerText but am unsure of how to go about doing it.

Please help out

Upvotes: 4

Views: 915

Answers (8)

Mamun
Mamun

Reputation: 68933

You can try with querySelectorAll() and Array.prototype.reduce().

Please Note: You are closing the elements in the wrong way (<li/>, <ul/>) which will create unexpected markup, should be </li>, </ul>.

let products = {
    oreos: 20,
    milk:  17,
    bread: 12,
    doritos: 10
};
function getTotal(li, prod){
  return Array.from(li).reduce((a,c) => a + prod[c.textContent], 0);
}
console.log(getTotal(document.querySelectorAll('li'), products));
<ul>
    <li>oreos</li>
    <li>milk</li>
</ul>

Upvotes: 1

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48600

You fist need to fix your end-tags; the slash comes before the final tag name.

Second, you can reduce all your list values by grabbing their text value and looking them up in the product list. You can use Array.from to translate a NodeList into an array so that you can call Array.prototype.reduce.

const products = {
    oreos: 20,
    milk:  17,
    bread: 12,
    doritos: 10
}

let total = calculateTotal(document.querySelector('ul.items'), products)

console.log(`Total = ${total}`)

function calculateTotal(ul, products) {
  return Array.from(ul.querySelectorAll('li'))
    .reduce((sum, li) => sum + products[li.textContent] || 0, 0)
}
<ul class="items">
    <li>oreos</li>
    <li>milk</li>
</ul>

Upvotes: 1

SleepingSpider
SleepingSpider

Reputation: 1228

function getPrice()
{
    let products = {
        oreos: 20,
        milk:  17,
        bread: 12,
        doritos: 10
    }

    var items = document.getElementsByTagName("li");
    var price = 0;

    for (i = 0; i < items.length; i++) {
        var item = items[i];
        var val = parseFloat(products[item.innerHTML]);
        price += val;    
    }

    alert("Total price is: " + String(price));
}

You can then hook the function getPrice to the onclick property of a button to see the result. You may want to give your lists a class, or give the ul an id, so that getPrice doesn't return all the lists on your HTML page.

Upvotes: 0

Safeer Raees
Safeer Raees

Reputation: 410

What you can do is that, you can use the following function:

let totalPrice = (priceList, products) => {
return products.reduce((total, elem) => {
    total += priceList[elem.innerText];
    return total;
}, 0)

}

This function iterates on list of products using Array.reduce and adds the list of product prices and returns the total.

You should checkout Array.reduce() for more clarity.

Upvotes: 5

Sarah Gro&#223;
Sarah Gro&#223;

Reputation: 10879

Here's what your function could look like:

  1. Iterate over all list items
  2. Get the text content of the item
  3. look up the price in the products object by using the text content as key
  4. add to the total
  5. return the total

I used Array.from() and Array.prototype.reduce() to achieve this all in one go. Of course you'd need a distinct class or even better an ID on the list instead of simply selecting all list items on the page.

let products = {
    oreos: 20,
    milk:  17,
    bread: 12,
    doritos: 10
}

function getTotal(listElements, productPrices) {
  var total = Array.from(listElements).reduce(function(total, listItem) {
    total += productPrices[listItem.textContent] || 0;
    return total;
  }, 0);
  return total;
}

console.log(getTotal(document.querySelectorAll('li'), products));
<ul>
    <li>oreos</li>
    <li>milk</li>
</ul>

Upvotes: 2

Mr. de Silva
Mr. de Silva

Reputation: 382

To put you in the right direction (untested):

From: https://www.sitepoint.com/community/t/looping-through-li-elements-in-ul/6049/2 and Check if a key exists inside a json object

<ul id="foo">
  <li>First</li>
  <li>Second</li>
  <li>Third</li>
</ul>

var ul = document.getElementById("foo");
var items = ul.getElementsByTagName("li");
for (var i = 0; i < items.length; ++i) {
  // do something with items[i], which is a <li> element
  if((items[i] in products)) alert("yeah");
}

Read this also: Looping through list items with jquery

  • This should put you in the right direction (may even work out of the box).

Trust this helps.

Upvotes: 0

Ayrton
Ayrton

Reputation: 2303

You can add an id, let's say "list" to your <ul>, then do something like this:

let list = document.getElementById("list");
let totals = {};

for(let key of products) {
    totals[key] = 0;
}

for(let i = 0; i < list.children.length; i++) {
    let child = list.children[i];

    let text = child.textContent;

    if(totals.hasOwnProperty(text)) {
        totals[text]++;
    }
}

let fullPrice = 0;

for(let key of products) {
    fullPrice += products[key] * totals[key];
}

console.log(fullPrice);

The code does the following:

  1. It creates a totals object, which will count the occurrences of each existing product in your products object.
  2. Then, it gets your <ul> element, and loops through its <li> children elements, taking the text of each <li> and looking it up in the totals object.
  3. If the product exists, it increases the count.
  4. Lastly, it calculates the full, final price by multiplying the totals with the prices.

PS: This code assumes there will be only <li> elements inside your list, and that each <li> holds only text.

Upvotes: 1

IceMetalPunk
IceMetalPunk

Reputation: 5556

Loop through the li elements, use their innerText as the key to lookup the price, sum them, and you're good:

let total = 0;
document.querySelectorAll('li').forEach(item => {
  total += products[item.innerText];
});

There are other forms of this, and little additions you could include (such as checking that the item actually exists in the products array first), but that's the basic idea.

Upvotes: 2

Related Questions