I am having difficulty calculating the total votes from the array of choices . I have a json like below
{
id:1,
pollName: 'aaaaa',
pollChoices:[
id: 2,
choice : 'dddd',
votes: [
{
}
]
]
}
I am trying to count the total number votes casted from the jon above within my memoized selectors
My code is like below
const pollChoices: Array<PollChoice> = poll.get("PollChoices").toJS();
const pollStatistic = pollChoices
.reduce((prev: any, curr: any) => {
console.log("The pollStatistic is ", prev);
return { curr, totalVotesCasted: (prev.Votes ?
(prev.Votes.length + curr.Votes.length) :
0 + curr.Votes.length )}
}, {});
console.log("The pollStatistic is ", pollStatistic);
The console within pollStatistic seems to show my totalVotesCasted, however, when i print pollStatistic, its always undefined, i want to be able to get the pollStatistic.totalCount in my state. Pls any help is appreciated.
This is not how reduce works.
You pass the reduce function a reducer callback of this signature: function reducer(accumulator, currentValue, currentIndex) { ... }
The callback should return a the value of the accumulator it wants to be passed to the next iteration.
In your case when you access prev.Votes you should be accessing prev.totalVotesCasted which is the value you set on the accumulator.
Related
I had a context's state that have an array with some objects inside of him. the objects are something like
state[
{
name: name,
value: 200,
unit: 2
},
{
name: othername,
value: 50,
unit: 1
}]
I need to multiply the value with the units and then sum with the other objects.
I tried to use
useEffect(()=>{
state.items.map((each) => {
return setSubtotal( previousValue => previousValue + each.unit * Number(each.price));
},[state])
it works for sum, but when i remove some object of the state, i dont know what i have to do to subtract the value. Someone can help me?
I hope this code will help you, I put a reducer on it
const subTotal = state.items.reduce((previousValue , each) => each.unit * Number(each.price) + previousValue , 0);
useEffect(()=>{
setSubtotal( subTotal );
},[subTotal])
In my state I have an object called foodLog which holds all entries a user enters with one of the keys being foodSelectedKey and I'm trying to return all entries that have a matching value from that key with a different array called foodFilter.
However, this doesn't work and errors out saying foodLog.filter() isn't a function - I've looked this up and it's because it's an Object (I think). Any help would be greatly appreciated!
state = {
// log food is for the logged entries
foodLog: {},
// used for when filtering food entries
foodFilter: [],
};
findMatches = () => {
let foodLog = this.state.foodLog;
let foodFilter = this.state.foodFilter;
let matched = foodLog.filter((item) => {
return foodLog.foodsSelectedKey.map((food) => {
return foodFilter.includes(food);
});
});
};
I guess the reason behind the error Is not a function is that the object can not be looped. By that it means you can not iterate an object with differend variables inside, if it has no index to be iterated like an array. The same goes for map(), find() and similar functions which MUST be run with arrays - not objects.
As far as I understand you have an object named foodLog which has an array named foodsSelectedKey. We need to find intersected elements out of foodFilter with the array. This is what I came up with:
state = {
// log food is for the logged entries
foodLog: {
foodsSelectedKey: [
{ id: 1, name: "chicken" },
{ id: 2, name: "mashroom" }
]
},
// used for when filtering food entries
foodFilter: [
{ id: 1, name: "chicken" },
{ id: 2, name: "orange" }
]
};
findMatches = () => {
let foodLog = this.state.foodLog;
let foodFilter = this.state.foodFilter;
let matched = foodLog.foodsSelectedKey.filter((key) =>
{
for (let i=0; i<foodFilter.length;i++){
if(foodFilter[i].name===key.name)
return true
}
return false;
}
);
return matched;
};
The Output is filtered array, in this case, of one element only:
[{
id: 1
name: "chicken"
}]
In order to check the output - run console.log(findMatches()). Here is the CodeSandbox of the solution. (check console at right bottom)
I have an array of objects as my initial state like
const [product,setProduct]=useState([
{
id:1,
product_title:"Item 1",
quantity:2,
price:100.00
},
{
id:2,
product_title:"Item 2",
quantity:3,
price:300.00
},
])
Here I am also adding more items and at the same time, I Want to calculate the total amount based on quantity*price of each item from the objects. Right now I am proceeding with map() function like this code below and I am getting the exact result
const countTotal=(items)=>
{
var total=0;
product.map(item=>total+=item.quantity*item.price)
setTotal(total)
}
Now My question is if it is a good process or there is an alternative way that is better and standard than this process.
As a general rule, if you have array and want to single value based on all values, you need Array.proptotype.reduce()
const products = [
{
id:1,
product_title:"Item 1",
quantity:2,
price:100.00
},
{
id:2,
product_title:"Item 2",
quantity:3,
price:300.00
},
];
const countTotal = (items) => items.reduce((acc, curr) => acc + curr.quantity * curr.price, 0);
console.log(countTotal(products))
You are using .map method incorrectly, you should use reduce method instead, like this
const total = product.reduce((prev, cur) => {
return prev + cur.quantity * cur.price;
}, 0);
For some reason my reducer is only returning a single element in the categories collection.
I'm just learning this accumlator logic, so I have kept it simple which I thought was suppose to simply return the exact same state as I started with.
My state in JSON looks like:
{
"account":{
"id":7,
"categories":[
{
"id":7,
"products":[
{
"productId":54
}
]
},
{
"id":9,
"products":[
{
"productId":89
}
]
}
]
}
}
In my reducer I have the following:
return {
...state,
account: {
...state.account,
categories: [state.account.categories.reduce((acc, cat) => {
return {...acc, ...cat}
}, {})]
}
};
When I output my state, I see that for some reason it has removed one of the categories from the collection.
Why isn't my state the same since the accumulator isn't filtering anything? It should be the exact same as it started with.
if you want to return categories unchanged (but with a different reference), you should do it like this:
categories: state.account.categories.reduce((acc, cat) => {
return [...acc, cat];
}, [])
In your code accumulator value is an object with categories props that is constantly overwritten by another item from an array so in the end only the last item is present.
Let's put aside react and redux and focus on reduce function. It takes an array and returns something different using the function called a reducer.
In the following example:
const array = [{num: 1}, {num: 2}];
you can take each of the elements of an array and merge their properties:
array.reduce((acc, item) => ({...acc, ...item}), {})
this is equal to
Object.assign({}, array[0], array[1]);
or
{...array[0], ...array[1]}
and result is {num: 2}, (first there was an empty object {}, then {num: 1} and finally {...{num: 1}, ...{num: 2}} gave {num: 2}
It doesn't matter if you enclose it in an array, it's still a one object created from merging all objects in the array together
If you want a copy of an array. This can be done like this:
array.reduce((acc, item) => [...acc, item], []);
This is equal to
[].concat(...array);
I have a Json Response
"carts": {
"value": [
{
"Amt": 40
},
{
"Amt": 20.25
},
{
"Amt": 10.30
}
]
}
I want to get the sum value of Amt field and the output should be 70.55
How to get this using Typescript.I am new to typescript.
Can anyone please help me with this?
The correct way of using JavaScript's reduce function (which is also valid for TypeScript) would be:
const response = {
"carts": {
"value": [
{
"Amt": 40
},
{
"Amt": 20.25
},
{
"Amt": 10.30
}
]
}
};
const total = response.carts.value.reduce((sum, item) => sum + item.Amt, 0);
console.log(total);
Note that if you want to support IE8 you have to include a polyfill (like that on MDN's page).
I am very much in favor of the Rxjs' Observable answer, but since no one else mentioned it : Javascript arrays have a reduce function, so one can use it in Typescript too !
// suppose variable carts already stores the deserialized json
let total: number = carts.value.reduce(
(a: number, b) => a + b.Amt, 0);
after #Stefan's comments :
Fixed mistakes &
better to not assign type of b, so that it will be inferred from the context and maybe raise a Typescript error at compile-time.
You can use observable reduce.
If you have Http response then:
this.http.get('url')
.map(response.carts.value)
.map(res => res.Amt)
.reduce((a, b) => a + b)
.subscribe(res => console.log(res))
let sum = 0;
for (var i = 0; i < this.carts.value.length; i++) {
sum+= this.carts.value[i].Amt;
}
You can write a function like this:
public cartTotal(): number {
let total: number = 0;
this.carts.value.forEach((e:any) => {
total = total + Number(e.Amt);
});
return total;
}
This is the basic way to do it.
sum=0;
for(let a of json.carts.value){
sum=sum+a.Amt;
}