react count object properties in an array - javascript

I am fetching data by an API. It is a movie, tv show, person database. When I search a word in the search box, it returns the related movie, tv show and person names in objects nested in an array. for example when I search "fight":
[
0:{original_name: "쌈 마이웨이", id: 70813, media_type: "tv", name: "Fight My Way", vote_count: 5,…}
1:{vote_average: 8.2, vote_count: 8057, id: 550, video: false, media_type: "movie", title: "Fight Club",…}
2:{vote_average: 6.1, vote_count: 215, id: 345922, video: false, media_type: "movie",…}
3:{original_name: "Fight", id: 46554, media_type: "tv", name: "Fight", vote_count: 0, vote_average: 0,…}
4:{original_name: "The Good Fight", id: 69158, media_type: "tv", name: "The Good Fight", vote_count: 22,…}
5:{vote_average: 0, vote_count: 0, id: 158301, video: false, media_type: "movie", title: "Fight",…}
]
there are more results but I cut them. As you can see there are media_type properties in each object. there are 3 media types as you can understand (movie, tv, person). I want to count each type.
actually; I want the same thing in the link I guess: React: Syntax for calling setState in Switch Return
but it doesn't work for me. I tried to change simply the state of movieCount to 3 like this:
countType() {
this.props.movies.map(movie => {
return() => {
if(movie.media_type === 'movie') {
this.setState({ movieCount: 3});
console.log(this.state);
}
}
});
}
but it doesn't work too.and I researched on the internet this stuff in javascript documentation and forums. not about just react. but I couldn't do anything. I know it's simple.
so how can I count objects in an array according to their property types?

Assuming that the data you fetched from API is stored in data variable, you can try the following code to find the count of movie media type in your data array:
const movies = data.filter(item => item.media_type === 'movie'));
const moviesCount = movies.length;
You can also dynamically calculate count of every media_type in your data array:
const mediaTypes = data
.map(dataItem => dataItem.media_type) // get all media types
.filter((mediaType, index, array) => array.indexOf(mediaType) === index); // filter out duplicates
const counts = mediaTypes
.map(mediaType => ({
type: mediaType,
count: data.filter(item => item.media_type === mediaType).length
}));
Then counts will be something like this:
[
{
"type": "tv",
"count": 3
},
{
"type": "movie",
"count": 3
}
]

ok i found the solition. thank you to poohitan for answer. i solved it
through his answer.
countType(type) {
const countTypes = this.props.movies.filter(movie => movie.media_type === type);
return countTypes.length;
}
and while i am rendering my tv results, i just call the method above with type. for example:
return (
<div>
movie count: {this.countType('movie')}
tv show count: {this.countType('tv')}
</div>
);

var data = [
{ original_name: "쌈 마이웨이", id: 70813, media_type: "tv", name: "Fight My Way", vote_count: 5 },
{ vote_average: 8.2, vote_count: 8057, id: 550, video: false, media_type: "movie", title: "Fight Club" },
{ vote_average: 6.1, vote_count: 215, id: 345922, video: false, media_type: "movie" },
{ original_name: "Fight", id: 46554, media_type: "tv", name: "Fight", vote_count: 0, vote_average: 0 },
{ original_name: "The Good Fight", id: 69158, media_type: "tv", name: "The Good Fight", vote_count: 22 },
{ vote_average: 0, vote_count: 0, id: 158301, video: false, media_type: "movie", title: "Fight" },
]
this.types = {};
data.forEach((d) => {
if (!this.types[d["media_type"]]) {
this.types[d["media_type"]] = 1;
} else {
this.types[d["media_type"]] += 1;
}
})
console.log(this.types);
// you will get answer { tv: 3, movie: 3 }

Here's one possible way:
render() {
let countTypes = ' '
return ({
list.length > 0
?
<span> {countTypes = (list.filter(moviesFilter =>
moviesFilter.type.id === this.props.typeId)).length}
</span>
:
<DisplayMessage message="0" />
})
}

Related

Best way to return a nested object the matches a property requested

I'm trying to create a new object that only contains the a product array with the seller I req. I have an order object that has a product array. I'd like to return a specific seller. I tried:
const newOrders = orders.map((element) => {
return {
...element,
product: element.product.filter(
(seller) => seller === req.currentUser!.id
),
};
});
does mongoose have a preferred method for doing what I bring to achieve? I've read through the find queries but none of the methods seem useful to this use case.
orders: [
{
userId: "638795ad742ef7a17e258693",
status: "pending",
shippingInfo: {
line1: "599 East Liberty Street",
line2: null,
city: "Toronto",
country: "CA",
postal_code: "M7K 8P3",
state: "MT"
},
product: [
{
title: "new image",
description: "a log description",
seller: "6369589f375b5196f62e3675",
__v: 1,
id: "63737e4b0adf387c5e863d33"
},
{
title: "Mekks",
description: "Ple",
seller: "6369589f375b5196f62e3675",
__v: 1,
id: "6376706808cf1adafd5af32f"
},
{
title: "Meeks Prodyuct",
description: "long description",
seller: "63868795a6196afbc3677cfe",
__v: 1,
id: "63868812a6196afbc3677d06"
}
],
version: 1,
id: "6388138170892249e01bdcba"
}
],
Im sure this can be improved, doesn't feel that its the best way possible but it gets the result. Like the previous answer you have to find first the order the seller is in then find the products than filter the seller by the id. I'm using typescript and there's a bug https://github.com/microsoft/TypeScript/issues/50769 so you have to use the bracket notation.
const orders = await Order.find({
"product.seller": req.currentUser!.id,
});
const allOrders = orders[0].product;
const sellerOrders = allOrders.filter((obj) => {
return obj["seller"] === req.currentUser!.id;
});

filter through array values inside object

I have an array of objects as below, I want to get the whole object where badge has outreach word. I tried to filter and find but it only give me a single word in the array, not the full object. Please help me sort this out, thanks.
carData: [
{
flowName: "Cars",
badge: ["content", "outreach"],
image: icons.car,
},
{
flowName: "linkedin",
badge: ["content"],
image: icons.linkedin,
},
{
flowName: "facebook",
badge: ["content"],
image: icons.facebook,
},
]
This is what I've tried:
console.log(state.carData.map(({badge}) => (badge.filter(i => i==="outreach"))).find(badge=>badge.length>0));
It gives the result ['outreach'].
const carData = [{
flowName: "Cars",
badge: ["content", "outreach"],
image: "icons.car",
},
{
flowName: "linkedin",
badge: ["content"],
image: "icons.linkedin",
},
{
flowName: "facebook",
badge: ["content"],
image: "icons.facebook",
},
]
console.log(carData.filter(car => car.badge.includes("outreach")))
carData.filter(x=>x.badge.includes("outreach"))
Try this
carData.filter((car) => {
car.badge.includes("outreach")
})

How to sort nested array of objects by date

I am creating simple News application, And i am using Firebase as back-end, I have stored News articles in Cloud firestore, In my fields i have News publication time hr:min:sec I want to sort received data by publication time, from the latest to the oldest, any solutions? Thanks in advance
var data = [
{ news: [
{ published_at: "2/22/2021",
imgUrl: "",
id: 159783,
title: "short descr",
date: "18:11:53",
previewText: "some kind of title" }
],
newsId: "5GTAbGLfS0hSCOkmTfHD"
},
{ news: [
{ id: 159783,
published_at: "2/22/2021",
previewText: "some kind of title2",
title: "short descr",
date: "17:19:53",
imgUrl: ""
}
],
newsId: "lw2hzVe0m3dbcmvBj4Vz" }
]
data.forEach((item)=>{
var singleItem = item.news
const finalResult = singleItem.sort((a, b) => b.date - a.date)
console.log(finalResult)
})
You can use string#localeCompare to sort time in hh:mm:ss format.
const data = [ { news: [ { published_at: "2/22/2021", imgUrl: "", id: 159783, title: "short descr", date: "18:11:53", previewText: "some kind of title" } ], newsId: "5GTAbGLfS0hSCOkmTfHD" }, { news: [ { id: 159783, published_at: "2/22/2021", previewText: "some kind of title2", title: "short descr", date: "17:19:53", imgUrl: "" } ], newsId: "lw2hzVe0m3dbcmvBj4Vz" } ];
data.sort((a,b) => b.news[0].date.localeCompare(a.news[0].date));
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I think you can do something like this
const finalResult = singleItem.sort((a, b) => Date.parse(`${b.published_at} ${b.date}`) - Date.parse(`${a.published_at} ${a.date}`))

How can I model data for a datable?

I have a datatable where I am using a framework.
For now I am only mocking data because I don't have straight directions from my boss yet.
In the datatable docs say this:
rows:
The rows prop is where you provide us with a list of all the rows that you want to render in the table. The only hard requirement is that this is an array of objects, and that each object has a unique id field available on it.
headers:
The headers prop represents the order in which the headers should appear in the table. We expect an array of objects to be passed in, where key is the name of the key in a row object, and header is the name of the header.
The headers are going to be hardcoded:
For that I have this:
const tableHeaders = [
{
key: 'device',
header: t('cancellations.device'),
},
{
key: 'ticketNumber',
header: t('cancellations.ticketNumber'),
},
{
key: 'itemsCancelled',
header: t('cancellations.itemsCancelled'),
},
{
key: 'requestDate',
header: t('cancellations.requestDate'),
},
{
key: 'status',
header: t('cancellations.status'),
},
{
key: 'requestedBy',
header: t('cancellations.requestedBy'),
},
];
And before I had this hardcoded which is what I need to model and keep it exactly as it is, not hardcoded but with real data:
const rows = [
{
id: 'a',
device: t('Device 1'),
ticketNumber: t('Ticket Number'),
itemsCancelled: t('Items Cancelled'),
requestDate: t('Request Date'),
status: t('Status'),
requestedBy: t('Requested By'),
},
{
id: 'b',
device: t('Device 2'),
ticketNumber: t('Ticket Number'),
itemsCancelled: t('Items Cancelled'),
requestDate: t('Request Date'),
status: t('Status'),
requestedBy: t('Requested By'),
},
{
id: 'c',
device: t('Device 3'),
ticketNumber: t('Ticket Number'),
itemsCancelled: t('Items Cancelled'),
requestDate: t('Request Date'),
status: t('Status'),
requestedBy: t('Requested By'),
}
];
And the real data comes like this:
"CancellationRequests": [
{
"accountId": 232279,
"billingCancelReasonId": null,
"createDate": "2018-09-18T11:28:47-07:00",
"id": 17195077,
"modifyDate": "2018-09-18T11:28:48-07:00",
"notes": null,
"statusId": 2,
"ticketId": 65626859,
"account": null,
"items": null,
"status": null,
"ticket": null,
"user": null,
"itemCount": null,
"__typename": "SoftLayer_Billing_Item_Cancellation_Request"
},
{
"accountId": 232279,
"billingCancelReasonId": null,
"createDate": "2018-09-10T11:11:05-07:00",
"id": 17183859,
"modifyDate": "2018-09-10T11:11:06-07:00",
"notes": null,
"statusId": 2,
"ticketId": 65169379,
"account": null,
"items": null,
"status": null,
"ticket": null,
"user": null,
"itemCount": null,
"__typename": "SoftLayer_Billing_Item_Cancellation_Request"
}
]
So, comparing the real data with the hardcoded rows, it should match like this:
id: row.id,
device: row.account,
ticketNumber: row..ticketId,
itemsCancelled: row.itemCount,
requestDate: row.createDate
status: row.status,
requestedBy: row.user,
I am getting the values like this:
data.SoftLayerCancellationRequests.map(item => item);
But I don't know how to assign them to the proper key: value in a new object.
PS: I am using Reactjs.
Library use for components: http://react.carbondesignsystem.com/?selectedKind=DataTable&selectedStory=with%20expansion&full=0&addons=1&stories=1&panelRight=0&addonPanel=REACT_STORYBOOK%2Freadme%2Fpanel
You have already done all the hard work. It's just a matter of creating a new mapped array using your key matching already shown in your question
const rows = APIArray.map(row => {
return {
id: row.id,
device: row.account,
ticketNumber: row.ticketId,
itemsCancelled: row.itemCount,
requestDate: row.createDate
status: row.status,
requestedBy: row.user
}
})

Javascript Array Manipulation - Is there a more declarative approach?

Thanks for taking a look here. I'm working with an API, and need to change the format of the data. Here's an example of the return data:
data: [
{
status: "planned work",
name: "123"
},
{
status: "all good",
name: "nqr"
}
];
Each train line has a name like "123" or "nqr", and I want to split each train into their own objects so that it would look something like this:
data: [
{
status: "planned work",
name: "1"
},
{
status: "planned work",
name: "2"
},
{
status: "planned work",
name: "3"
},
{
status: "all good",
name: "n"
},
{
status: "all good",
name: "q"
},
{
status: "all good",
name: "r"
}
];
I have some working code which splits the name and uses nested .forEach loops to push items to an array. Working code:
function formatLinesData(lines) {
var trains = [];
lines.forEach( line => {
line.name.split("").forEach(train => {
trains.push({name: train, status: line.status});
});
});
return trains;
}
Is there a way to accomplish this without the nested loops? Looking for an elegant solution if you have one.
Thanks
You might do as follows;
var data = [
{
status: "planned work",
name: "123"
},
{
status: "all good",
name: "nqr"
}
],
newData = [].concat(...data.map(o => o.name.split("").map(c => ({status: o.status, name: c}))));
console.log(newData);
You can use reduce - initialize it with an empty array, and iterate over the data
array using your logic.
data.reduce((prev,curr) => {
for (let i=0; i<curr.name.length; i++) {
prev.push({ name : curr.name[i], status : curr.status});
}
return prev;
},[]);

Categories