Good day everyone, I've the following problem, I've some arrays with information about different products, each product has a rating, when I want to take that assessment and make an average to rate the store, it does not recognize the values.
Could someone tell me what I am doing wrong or how I could improve? Thank you
This is my Typscript
Review(i, totalReviews) {
let globalRating = 0;
let globalReviews = 0;
setTimeout(function () {
totalReviews.forEach((review, index) => {
globalRating = review.length;
for (const i in review) {
globalReviews = review[i].review;
console.log("I", review[i]);
}
})
console.log("Raiting", globalRating);
console.log("globalReviews", globalReviews);
let averageReviews = Math.round(globalReviews / globalRating);
let precentage = Math.round(globalReviews * 100 / (globalRating * 5));
let averageRating = DinamicReviews.fnc(averageReviews);
$(".br-theme-fontawesome-stars").html(`
<select class="ps-rating reviewsOption" data-read-only="true"></select>
`)
for (let i = 0; i < averageRating.length; i ) {
$(".reviewsOption").append(`
<option value="${averageRating[i]}">${i 1}</option>
`)
}
Rating.fnc();
}, i * 100)
}
CodePudding user response:
ES6 introduced the super awesome reduce
method for arrays.
The reduce() method executes a user-supplied “reducer” callback function on each element of the array, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value.
Perhaps the easiest-to-understand case for reduce() is to return the sum of all the elements in an array.
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
It's a little unclear what the global reviews are as well as rating. Where does the number 15 come from?
Anyhow, you could do something like this:
const array = [
{review: 4, comment: 'Lorem Ipsum' },
{review: 5, comment: 'Lorem Ipsum' },
{review: 4, comment: 'Lorem Ipsum' },
{review: 3, comment: 'Lorem Ipsum' },
{review: 4, comment: 'Lorem Ipsum' },
{review: 5, comment: 'Lorem Ipsum' },
{review: 5, comment: 'Lorem Ipsum' },
{review: 4, comment: 'Lorem Ipsum' },
{review: 5, comment: 'Lorem Ipsum' },
{review: 4, comment: 'Lorem Ipsum' },
{review: 3, comment: 'Lorem Ipsum' },
{review: 4, comment: 'Lorem Ipsum' },
{review: 5, comment: 'Lorem Ipsum' },
{review: 5, comment: 'Lorem Ipsum' }
];
const getAvrgRating = (arr) => {
return Math.round(arr.reduce((total, obj) => obj.review total,0) / arr.length);
};
const getGlobalRating = (arr) => {
return arr.length;
};
const getPercentage = (partial, total) => {
if (partial === 0 && total === 0) {
return 0;
}
return Math.round((partial / total) * 100);
};
const rateStore = (arr) => {
console.log(`Global rating: ${getGlobalRating(arr)}`);
console.log(`Average rating: ${getAvrgRating(arr)}`);
console.log(`Percentage: ${getPercentage(getAvrgRating(arr), getGlobalRating(arr))}`);
};
rateStore(array);
The overall logic should be applicable to your case.
- How to get an average value of an object key, based on an array of objects.
- How to calculate percentages.
- Aggregating the values into desired information.
Feel free to adjust the values in order to get your desired results, since some of your values weren't really explained.
If you want your percentages to be more precise, you can remove the Math.round()
method.
If you'd like a case with n decimal values in your percent, you could use the toFixed()
method. However, note that this will automatically convert the return type to string
. If you expect a number, you'd have to convert it into float with the parseFloat()
method.
console.log(`string value: ${((4 / 14) * 100).toFixed(2)}`);
console.log(`number value: ${parseFloat(((4 / 14) * 100).toFixed(2))}`);
CodePudding user response:
As per the comments in the question, you are using the incorrect properties on the array and doing unnecessary DOM updates that cause reflows in the browser.
Instead, build up the element you need in memory and only append it to the DOM once.
To calculate the total, you can use Array.reduce and use Array.length to determine the number of reviews.
See comments inline:
const reviews = [{
review: 2,
comment: 'Lorem Ipsum'
},
{
review: 4,
comment: 'Lorem Ipsum'
},
];
const processReviews = (reviews) => {
const totalRating = reviews.reduce((previousValue, currentValue) => previousValue currentValue.review, 0);
const averageRating = Math.round(totalRating / reviews.length); // If the fractional portion of the argument is greater than 0.5, the argument is rounded to the integer with the next higher absolute value.
// the rest is simply UI
// create the select element and options
const fragment = document.createDocumentFragment();
const select = document.createElement('select');
select.className = 'ps-rating reviewsOption';
select.dataset.readOnly = true;
fragment.appendChild(select);
for (let i = 0; i < 5; i ) {
const option = document.createElement('option');
option.value = option.text = i 1;
option.selected = (i 1) === averageRating;
select.appendChild(option);
}
// update the DOM once
document.querySelector('.br-theme-fontawesome-stars').appendChild(fragment);
// debugging
console.info(`reviews: ${reviews.length}, totalRating: ${totalRating}, average: ${averageRating}`);
}
processReviews(reviews);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="br-theme-fontawesome-stars" />