FInd and removed nested elements from array in javascript? - javascript

I have a json below like this
[
{
"monthlyData": [
{
"dateYear": "2020-07",
"data": [
{
"id": "45bf4792-c5a5-44ed-b7e8-57557c4f30ee",
"date": "2020-07-13T00:00:00.000Z",
"transactionId": "160",
"amount": 70,
"active": 1,
"createdAt": "2020-07-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}
]
}
],
"hashId": "4"
},
{
"monthlyData": [
{
"dateYear": "2020-08",
"data": [
{
"id": "38fe3c68-e6aa-4c57-b4d7-dc6c4f597269",
"date": "2020-08-13T00:00:00.000Z",
"transactionId": "146",
"active": 1,
"createdAt": "2020-08-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}
]
}
],
"hashId": "5"
}
]
I have an array with list of month-year as
let datesArr = ['2020-08','2020-09','2020-10','2020-11','2020-07']
Now I want to pick a date from datesArr one by one and find if the date matches with dateYear column in whole JSON array. A copy of JSON array should be created for those dates are matched. I want to keep only those object whose dates are getting matched.

You can use array.filter
let originalArray = [
{
"monthlyData": [
{
"dateYear": "2020-07",
"data": [
{
"id": "45bf4792-c5a5-44ed-b7e8-57557c4f30ee",
"date": "2020-07-13T00:00:00.000Z",
"transactionId": "160",
"amount": 70,
"active": 1,
"createdAt": "2020-07-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}
]
}
],
"hashId": "4"
},
{
"monthlyData": [
{
"dateYear": "2020-08",
"data": [
{
"id": "38fe3c68-e6aa-4c57-b4d7-dc6c4f597269",
"date": "2020-08-13T00:00:00.000Z",
"transactionId": "146",
"active": 1,
"createdAt": "2020-08-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}
]
}
],
"hashId": "5"
}
];
let datesArr = ['2020-08','2020-09','2020-10','2020-11'];
let filtered = originalArray.filter(value => {
value.monthlyData = value.monthlyData.filter(md => {
return datesArr.includes(md.dateYear);
})
return value.monthlyData.length > 0;
})
console.log(JSON.stringify(filtered))
This example will print this below (if that is what you want):
[
{
"monthlyData": [
{
"dateYear": "2020-08",
"data": [
{
"id": "38fe3c68-e6aa-4c57-b4d7-dc6c4f597269",
"date": "2020-08-13T00:00:00.000Z",
"transactionId": "146",
"active": 1,
"createdAt": "2020-08-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}
]
}
],
"hashId": "5"
}
]
Edit for date object comparison
if datesArr is like
let datesArr = [new Date('2020-08'),new Date('2020-09')];
You can use array.some inside second filter
let filtered = originalArray.filter(value => {
value.monthlyData = value.monthlyData.filter(md => {
return datesArr.some(value1 => value1.getTime() === new Date(md.dateYear).getTime());
})
return value.monthlyData.length > 0;
})
And of course if original array has also Date object, you can discard
new Date(md.dateYear).getTime() use md.dateYear.getTime() instead
Edit for your comment:
I need to add those dates into monthData who has not matched with
datesArray with data as empty. what should i do.
You can use below code for that
let newArr = []
datesArr.forEach(date => {
let element = originalArray.find(value => {
value.monthlyData = value.monthlyData.filter(md => {
return date === md.dateYear;
})
return value.monthlyData.length > 0;
})
if (!element){
element = {
"monthlyData": [
{
"dateYear": date,
"data": []
}
],
"hashId": "something?"
}
}else {
// make a clone
element = JSON.parse(JSON.stringify(element))
}
newArr.push(element);
})

You can do it efficiently with Javascript's forEach
The code below extracts the information you require.
const bigTable = [{
"monthlyData": [{
"dateYear": "2020-07",
"data": [{
"id": "45bf4792-c5a5-44ed-b7e8-57557c4f30ee",
"date": "2020-07-13T00:00:00.000Z",
"transactionId": "160",
"amount": 70,
"active": 1,
"createdAt": "2020-07-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}]
}],
"hashId": "4"
},
{
"monthlyData": [{
"dateYear": "2020-08",
"data": [{
"id": "38fe3c68-e6aa-4c57-b4d7-dc6c4f597269",
"date": "2020-08-13T00:00:00.000Z",
"transactionId": "146",
"active": 1,
"createdAt": "2020-08-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}]
}],
"hashId": "5"
}
]
const datesArr = ['2020-08', '2020-09', '2020-10', '2020-11', '2020-07']
console.log("Version 1: a separate object for each dateYear")
datesArr.forEach(dateYear => {
console.log(dateYear+":-------------------");
bigTable.forEach(monthlyArray => {
monthlyArray.monthlyData.forEach(monthData => {
if (dateYear === monthData.dateYear) {
console.log(monthData)
}
})
})
})
console.log("Version 2: a single array with an element for each element of datesArr")
const output = datesArr.map(dateYear => bigTable.filter(monthlyObject =>
monthlyObject.monthlyData[0].dateYear=== dateYear
)
)
console.log(output)
Depending on exactly how you want it to compile the result, which is not unambiguous from your question, you should be able to adjust it to your needs.
Without an example of the output that you want, all we can do is guess what you mean.

Related

Remove data from my nested array of objects by matching values

Remove data from my nested array of objects by matching values. In my case I want to strip out the objects that are NOT active. So every object that contains active 0 needs to be removed.
[
{
"id" : 1,
"title" : 'list of...',
"goals": [
{
"id": 1569,
"active": 0
},
{
"id": 1570,
"active": 1
},
{
"id": 1571,
"active": 0
}
],
},
{
"id" : 2,
"title" : 'more goals',
"goals": [
{
"id": 1069,
"active": 0
},
{
"id": 1070,
"active": 1
},
],
},
]
The following will return the array in an unchanged status
public stripGoalsByInactiveGoals(clusters) {
return clusters.filter(cluster =>
cluster.goals.filter(goal => goal.active === 1)
);
}
array.filter wait a boolean to know if it has to filter data or not
in your case you have an array of array, you want to filter "sub" array by active goal
if you want to keep only active goals change your first filter by map to return a modify value of your array filtered by a condition
function stripGoalsByInactiveGoals(clusters) {
return clusters.map(cluster => {
return {
goals: cluster.goals.filter(goal => goal.active)
};
});
}
var data = [{
"goals": [{
"id": 1569,
"active": 0
},
{
"id": 1570,
"active": 1
},
{
"id": 1571,
"active": 0
}
],
},
{
"goals": [{
"id": 1069,
"active": 0
},
{
"id": 1070,
"active": 1
},
],
},
];
function stripGoalsByInactiveGoals(clusters) {
return clusters.map(cluster => {
return {
goals: cluster.goals.filter(goal => goal.active)
};
});
}
console.log(stripGoalsByInactiveGoals(data));
You can create another array (for the case when you need the input unchanged as well) and loop the input, appending each member objects' filtered goals array. You could also avoid appending the item if goals is empty after the filter, but this example doesn't do this, because it was not specified as a requirement.
let input = [
{
"goals": [
{
"id": 1569,
"active": 0
},
{
"id": 1570,
"active": 1
},
{
"id": 1571,
"active": 0
}
],
},
{
"goals": [
{
"id": 1069,
"active": 0
},
{
"id": 1070,
"active": 1
},
],
},
]
let output = [];
for (let item of input) {
output.push({goals: item.goals.filter(element => (element.active))})
}
console.log(output);
You can follow this for a dynamic approach:
stripGoalsByInactiveGoals(clusters) {
var res = [];
this.data.forEach((item) => {
let itemObj = {};
Object.keys(item).forEach((key) => {
itemObj[key] = item[key].filter(x => x.active != 0);
res.push(itemObj);
});
});
return res;
}
Stackbiltz Demo

Sort array of objects by the length of a field using lodash [duplicate]

This question already has answers here:
How to sort an array based on the length of each element?
(12 answers)
Closed 1 year ago.
I have an array like below, and I need to sort the array by the string length of name field.
for an example,
[
{
"_id": 10,
"name": "AAAAAA"
},
{
"_id": 11,
"name": "AA"
},
{
"_id": 12,
"name": "AAAA"
},
{
"_id": 13,
"name": "A"
},
{
"_id": 14,
"name": "AAAAAAAA"
}
]
I need the array like this,
[
{
"_id": 13,
"name": "A"
},
{
"_id": 11,
"name": "AA"
},
{
"_id": 12,
"name": "AAAA"
},
{
"_id": 10,
"name": "AAAAAA"
},
{
"_id": 14,
"name": "AAAAAAAA"
}
]
can any one help me out with this. Thanks.
This can be accomplished with the _.orderBy method:
_.orderBy(data, [({ name }) => name.length, 'name'], ['desc']);
Here is a break-down:
I threw some "B"s into the mix to show the secondary sorting (after length is compared). Sorting the length alone is not unique enough.
const data = [
{ "_id": 1, "name": "AAAAAA" },
{ "_id": 2, "name": "AA" },
{ "_id": 3, "name": "AAAA" },
{ "_id": 4, "name": "A" },
{ "_id": 5, "name": "AAAAAAAA" },
{ "_id": 6, "name": "BBBBBB" },
{ "_id": 7, "name": "BB" },
{ "_id": 8, "name": "BBBB" },
{ "_id": 9, "name": "B" },
{ "_id": 10, "name": "BBBBBBBB" }
];
const sorted = _.orderBy(
data, // Data to be sorted
[
({ name: { length } }) => length, // First, sort by length
'name' // Them sort lexicographically
], [
'desc', // Length (descending)
'asc' // This is implied, and could be removed
]
);
console.log(sorted);
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

How can i make json file like this when i input

How can i make the cart_items like my expetation.. just it no more.. my problem just it :D
i just wanna make my cart_items like this.. hope you are can help me thanks. did I make the wrong method? and one more thing, i wanna make the qty inside the cart_items
this is my expectation
"cart": [
{
"id": 1,
"date": "12/10/2020",
"store": {
"id": 1,
"name": "Dirumah Aja",
"promo": 1
},
"cart_items": [
{
"id": 1,
"product": {
"id": 1,
"name": "Bakso Urat",
"price": 10000,
"promo": {
"nama": "promo"
}
},
"qty": 5
}
]
}
]
and this is what I got
"cart": [
{
"cart_items": {
"name": "Steak Sapi Impor",
"price": "38000",
"stock": "4",
"image": "https://firebasestorage.googleapis.com/v0/b/francise-fb70a.appspot.com/o/steak.jpg?alt=media&token=46e0d769-96d3-440f-8edb-5fce2481ace0",
"promo": 3,
"id": 8,
"qty": 1
},
"store": {
"name": "Amanda Foods Store",
"email": "amanda#food.com",
"store_image": "https://firebasestorage.googleapis.com/v0/b/francise-fb70a.appspot.com/o/full_hd_retina.jpeg?alt=media&token=3e602e86-661b-48ee-9e9c-af9f94a170d1",
"product": [
5,
7,
8,
2
],
"store_promo": 1,
"location": {
"street_name": "Jl. Kebon Gedang II B",
"province": "Jawa Barat",
"city": "Bandung",
"post_code": "40285"
},
"id": 1
},
"date_order": "Nov 03 2020 08:48:03",
"id": 2
}
]
This is my data
data() {
return {
promo_id: [],
promo_partner: [],
products: {},
qty: 1,
cart_items: [
{}
]
};
and this is my method
addToCart() {
const date = (new Date()).toString().split(' ').splice(1,4).join(' ')
this.products.cart_items = this.product;
this.products.cart_items.qty = this.qty;
this.products.store = this.partner;
this.products.date_order = date;
console.log(this.cart_items)
axios
.post("http://localhost:3000/cart/", this.products)
.then(() => {
swal("Belanja Berhasil!", {
icon: "success",
});
})
.catch((error) => console.log(error));
}
}
You need to use .push() to add items to an array. You're replacing the array with this.product.
if (!this.products.cart_items) { // initialize cart_items if necessary
this.products.cart_items = [];
}
this.products.cart_items.push({id: this.product.id, product: this.product, qty: this.qty});

How to sort object according to nested array elements

I need to sort the main data by the oldest created account.
In the example below, the first element in the list would be id = 2. That's because the id = 2 contains the oldest created account (named account3, which was created at 2020-10-05, while the other accounts have been created after that date).
I'm using nodejs. Is there an es-function that can solve this problem in an easy way?
The object data looks like this:
{
"data": [{
"id": 1,
"accounts": [{
"id": 333,
"data": {
"name": "account1",
"createdAt": "2020-10-07T09:27:28.032Z"
}
}]
}, {
"id": 2,
"accounts": [{
"id": 334,
"data": {
"name": "account2",
"createdAt": "2020-10-06T09:27:28.032Z"
}
}, {
"id": 335,
"data": {
"name": "account3",
"createdAt": "2020-10-05T09:27:28.032Z"
}
}]
}]
}
You can often solve this problem with map --> sort --> map.
It does 3 passes on the input but remains O(n log n). You could further optimize, but I doubt this becomes a bottleneck.
Map to [record, oldestAccountDate] tuples.
Sort the tuples by oldestAccountDate.
Map again to unwrap the record.
const wrapper = {
"data": [{
"id": 1,
"accounts": [{
"id": 333,
"data": {
"name": "account1",
"createdAt": "2020-10-07T09:27:28.032Z"
}
}]
}, {
"id": 2,
"accounts": [{
"id": 334,
"data": {
"name": "account2",
"createdAt": "2020-10-06T09:27:28.032Z"
}
}, {
"id": 335,
"data": {
"name": "account3",
"createdAt": "2020-10-05T09:27:28.032Z"
}
}]
}]
};
wrapper.data = wrapper.data
.map(rec => [rec, Math.min(...rec.accounts.map(acc => new Date(acc.data.createdAt)))])
.sort((a, b) => a[1] - b[1])
.map(tuple => tuple[0]);
console.log(wrapper);
const data = [{
"id": 1,
"accounts": [{
"id": 333,
"data": {
"name": "account1",
"createdAt": "2020-10-07T09:27:28.032Z"
}
}]
}, {
"id": 2,
"accounts": [{
"id": 334,
"data": {
"name": "account2",
"createdAt": "2020-10-06T09:27:28.032Z"
}
}, {
"id": 335,
"data": {
"name": "account3",
"createdAt": "2020-10-05T09:27:28.032Z"
}
}]
}]
const sorted = data.sort((a, b) => {
const aOldestDate = a.accounts.reduce((acc, item) => {
const itemDate = new Date(item.data.createdAt);
return itemDate < acc && itemDate || acc;
}, new Date());
const bOldestDate = b.accounts.reduce((acc, item) => {
const itemDate = new Date(item.data.createdAt);
return itemDate < acc && itemDate || acc;
}, new Date());
return aOldestDate - bOldestDate;
});
console.log(sorted);

How to groupBy in multi arrays using lodash

I want to group By sub-work in array
Here is my array I want to group By sub-work
result = [
{
"date": "10-07-2019",
"data": [
{
"data_id": "20",
"work": "work_1",
"sub-work": "sub_work1",
"sub-data": [
{
"id": 7,
"title": 'subdata-1',
}
]
}
]
},
{
"date": "12-07-2019",
"data": [
{
"data_id": "20",
"work": "work_1",
"sub-work": "sub_work1",
"sub-data": [
{
"id": 7,
"title": 'subdata-1',
}
]
}
]
},
]
Here is what I try
result = _(result)
.map(function(items, data) {
_.groupBy(items.data, function({ sub_work }) {
return sub_work;
});
})
.value();
first I map result into data then I try to groupby but It's return null
Update
I want my output look like this
[
{
"date": "10-07-2019",
sub-work: [{
sub-work : "sub_work1",
sub-data[
{
"id": 7,
"title": 'subdata-1',
}
]
}]
}
]
...........................
It would be better if you could provide your expected result.
Here's what I could infer:
_(result)
.map(function(obj) { // Convert into a 2D array.
return obj.data.map(e => Object.assign(e, {date: obj.date}));
})
.flatten() // We have an array of objects now.
.groupBy('sub-work') // We can call groupBy().
.value();
Here's what you get:
{
"sub_work1": [{
"data_id": "20",
"work": "work_1",
"sub-work": "sub_work1",
"sub-data": [{
"id": 7,
"title": "subdata-1"
}],
"date": "10-07-2019"
}, {
"data_id": "20",
"work": "work_1",
"sub-work": "sub_work1",
"sub-data": [{
"id": 7,
"title": "subdata-1"
}],
"date": "12-07-2019"
}]
}

Categories

Resources