I would like to count and show how much data are covered in each array. At first, I filtered and set only the label which is not duplicated. And then I counted each as array. But it wouldn't work...
dataArray = ["a", "a", "bs", "bs", "bs", "bs", "vgvg"]
const [count, setCounts] = useState<any[]>([])
const [labels, setLabels] = useState<any[]>([])
useEffect(() => {
let b = dataArray.filter((x, i, self) => {
return self.indexOf(x) === i
})
setLabels(b)
console.log(label)
// ["a", "bs", "vgvg"]
}, [dataArray])
useEffect(() => {
let c = [] as any[]
dataArray.map((data) => {
c[data] = (c[data] || 0) + 1
})
setCounts(c)
console.log(count)
// {"a": 2, "bs": 4, "vgvg": 1}
}, [dataArray])
return (
{labels.map((label, idx) => (
<div>{label}: {counts[label]}</div>
))}
)
error
Element implicitly has an 'any' type because index expression is not of type 'number'.
You could probably use something like Array.prototype.reduce for this.
You could:
const TestComponent = ({ dataArray }) => {
// Memoise the counts so it doesn't need to be calculated on each render.
const counts = useMemo(() => {
// use array reduce to calculate counts.
return dataArray.reduce(
(state, item) => {
// if property does not yet exist add it and set to 0 count.
if (state[item] === undefined) {
state[item] = 0;
}
// increment count
state[item]++;
// return updated state
return state;
},
{} //initial state
);
}, [dataArray]);
return (
{
Object
// Use Object.keys to get an array of property names
.keys(counts)
// Map property names to desired view (label / count)
.map((key) => (
<div
key={key}
>
{key}: counts[key]
</div>
))
}
)
}
The example reduce function given a dataArray of:
const dataArray = ["a", "a", "bs", "bs", "bs", "bs", "vgvg"]
Would reduce to:
const result = {
a: 2,
bs: 4,
vgvg: 1
}