I need to restructure the JSON object with existing key values, please check below input format of JSON
{
'Demo-1': [
{
sku: 'Brisk',
count: '2',
},
{
sku: 'Pepsi Cans',
count: '2',
},
{
sku: 'Pepsi Cans',
count: '4',
}
],
'Demo-2' :{
"A":[
{
sku: 'Mountain',
count: '4',
},
{
sku: 'Pepsi Bottles',
count: '4',
}
],
"B":[
{
sku: 'Lipton Dietgreentea',
count: '2',
},
{
sku: 'Lipton Dietgreentea Mixedberry',
count: '2',
}
]
}
}
In the above input JSON, the "Demo-1" have a single array of object and the second one has two array object.
I would like to change the above array, into like below
Result
{
'Demo-1': {
items: [{
sku: 'Brisk',
count: '2',
},
{
sku: 'Pepsi',
count: '2',
},
{
sku: 'Pepsi',
count: '4',
}
],
mode: "Veri",
istatus: "open"
},
'Demo-2': {
"items":{
"A" :[
{
sku: 'Mountain',
count: '4',
},
{
sku: 'Pepsi Bottles',
count: '4',
}
],
"B" :[
{
sku: 'Lipton Dietgreentea',
count: '2',
},
{
sku: 'Lipton Dietgreentea Mixedberry',
count: '2',
}]
},
mode: "Doubled",
istatus: "Closed"
}
}
I already using below code solution for partially achiving this
Object.fromEntries(
Object.entries(obj).map(
([key, items]) => [key, { items, mode: "verification", status: "open" }]
)
)
Now if the object has two array objects like Demo-2, the mode value should be "Doubled"
please help me out in resolving this.
Thanks in advance.
You need to add condition into your mapping function.
Proper condition depends on what possible items values may be.
If items always either array or { A, B } object, following condition is enough:
Object.fromEntries(
Object.entries(obj).map(
([key, items]) => [key, { items, mode: Array.isArray(items) ? 'Single' : 'Doubled', status: 'open' }]
)
)
Related
below is an array of objects.
const input = [
{
id: '1',
productType: [
{
id: '2',
itemTypes: [
{
id: '3',
},
],
},
]
itemTypes: [
{
id: '4',
}
],
},
{
id: '2',
productType: [
{
id: '7',
itemTypes: [
{
id: '8',
},
],
},
{
id: '9',
itemTypes: [],
},
],
itemTypes: [
{
id: '5',
},
{
id: '6',
},
],
},
{
id: '9',
productType: [
{
id: '11',
itemTypes: [],
},
],
itemTypes: [],
},
]
so from above array i want to filter out the object that doesnt has itemTypes within producttypes as empty and itemTypes array empty.
so the expected output is below,
const output = [
{
id: '1',
productType: [
{
id: '2',
itemTypes: [
{
id: '3',
},
],
},
]
itemTypes: [
{
id: '4',
}
],
},
{
id: '2',
productType: [
{
id: '7',
itemTypes: [
{
id: '8',
},
],
},
{
id: '9',
itemTypes: [],
},
],
itemTypes: [
{
id: '5',
},
{
id: '6',
},
],
},
];
i have tried something like below,
const output = input.filter(e => e.includes(!isEmpty(productTypes.itemTypes) && !isEmpty(itemTypes));
but the problem above is productTypes is an array and i need to check if every object in productType has itemTypes empty array.
how can i do that. could someone help me with this. thanks.
You can try this:
const output = input.filter(
item => item.productType.some(
product => product.itemTypes.length > 0));
This question already has answers here:
Merge two array of objects based on a key
(23 answers)
Closed 4 months ago.
I have 2 different arrays, that i want to combine.
The first one looks like following:
const Cats[] = [
{ id: '1', name: 'Smiley' },
{ id: '2', name: 'Purple' },
]
the second one:
const catAges[] = [
{ id: '4', age: '13', catId: '1' },
{ id: '5', age: '4', catId: '2' },
];
and i want to combine them where id from Cats[] and catId from catAges[] are the same and have a result like following:
{ id: '4', age: '13', cat: { id: '1', name: 'Smiley' } },
{ id: '5', age: '4', cat: { id: '2', name: 'Purple' } },
i get the arrays from 2 different async functions looking like this:
const cats = [await getByCatId("1"), await getByCatId("2")];
const catsAge = await getCatsAges();
But i need help in how i combine these 2 and map them. I've tried something like this but without any success:
const all = (cats, catsAge) =>
cats.map(cats=> ({
...catsAge.find((cats) => (catsAge.catId === cats.id) && catsAge),
...cats
}));
console.log(all(cats, catsAge));
Thankful for any help in how to move forward.
const Cats = [
{ id: '1', name: 'Smiley' },
{ id: '2', name: 'Purple' },
]
const catAges = [
{ id: '4', age: '13', catId: '1' },
{ id: '5', age: '4', catId: '2' },
];
const transformed = catAges.map(item => {
const cat = Cats.find(cat => cat.id === item.catId);
if (cat) {
item.cat = cat;
delete item.catId;
}
return item;
});
console.log(transformed);
The problem with your function is just that you're re-using the cats variable too much, so in your .find comparision you're comparing an element from catsAge (as cats.id) and the catsAge array (as catsAge.catId) which is undefined.
Try this:
const all = (cats, catsAge) =>
cats.map((cat) => ({
...catsAge.find((catsAge) => catsAge.catId === cat.id),
...cat,
}));
Pro tip: Learn+Use Typescript and the compiler would catch these errors for you :)
const Cats = [
{ id: '1', name: 'Smiley' },
{ id: '2', name: 'Purple' },
]
const catAges = [
{ id: '4', age: '13', catId: '1' },
{ id: '5', age: '4', catId: '2' },
];
catAges.map(catage => {
const cat = Cats.find(c => c.id == catage.catId);
if(cat) {
delete catage.catId;
catage.cat = cat;
return catage;
}
});
I have a data model which looks like this, so each documents has services array and each service contains an items array and I want to update properties in items array.
{
services: [
{
id: '1',
name: 'Service 01',
items: [
{
id: '1',
name: '',
qty: 10
},
{
id: '2',
name: '',
qty: 10
},
]
},
{
id: '2',
name: 'Service 02',
items: [
{
id: '3',
name: '',
qty: 10
},
{
id: '4',
name: '',
qty: 10
},
]
},
]
}
I want to set all the quantities inside services -> items to 0, What will be query for doing it I tried to do,
updateMany({}, { $set: { 'services.items.qty': 0 } });
but it's not working.
Let me know if you need more details.
the all positional operator $[] operator can be used to update all elements
playground
db.collection.update({},
{
$set: {
"services.$[].items.$[].qty": 0
}
})
i have the data structure like below,
const items = {
id: '1',
Orders: [
{
id: '1',
title: 'Order1',
startDate: "2019-08-13T00:00:00.000Z",
status: 'new',
}
{
id: '2',
title: 'Order2',
startDate: "2020-08-13T00:00:00.000Z",
status: 'done',
}
],
subItems: [
{
id: '1',
Orders: [
{
id: '1',
title: 'subitem-order1',
status: 'new',
startDate: '2019-08-13T00:00:00.000Z',
}
{
id: '2',
title: 'subitem-order2',
status: 'new',
startDate: '2020-08-13T00:00:00.000Z',
}
]
}
]
}
I want to order the orders by startdate in ascending order and subitem orders by startdate in ascending order.
so the output should be something like below,
const items = {
orders: [
{
id: '2',
title: 'Order2',
startDate: "2020-08-13T00:00:00.000Z",
status: 'done',
},
{
id: '1',
title: 'Order1',
startDate: "2019-08-13T00:00:00.000Z",
status: 'new',
},
]
subItems: [
{
id: '2',
title: 'subitem-order2',
status: 'new',
startDate: '2020-08-13T00:00:00.000Z',
},
{
id: '1',
title: 'Order1',
startDate: "2019-08-13T00:00:00.000Z",
status: 'new',
},
]
}
How can i group the orders in ascending order based on their startdate and subitems orders in ascending order based on their startdate. could someone help me with this. thanks.
Fortunately your startDate is an ISO datetime, so an alphabetical sort will deliver the correct temporal ordering. Let's exploit this!
Remember that the key by which you are sorting is a string, and not a number. A convenient way to sort by a string key is using localeCompare, which has the useful feature of taking two strings and returning a number appropriate for sorting.
Because the sorting is simple to deliver with localeCompare, you can do each list's sorting as a one-liner, which allows you to "build" the result object in an easy-to-understand way, as follows:
const rawItems = {
orders: [
{
id: '2',
title: 'Order2',
startDate: "2020-08-13T00:00:00.000Z",
status: 'done',
},
{
id: '1',
title: 'Order1',
startDate: "2019-08-13T00:00:00.000Z",
status: 'new',
},
],
subItems: [
{
id: '2',
title: 'subitem-order2',
status: 'new',
startDate: '2020-08-13T00:00:00.000Z',
},
{
id: '1',
title: 'Order1',
startDate: "2019-08-13T00:00:00.000Z",
status: 'new',
},
]
}
const items = {
orders: rawItems.orders.sort(
(order1,order2) => order1.startDate.localeCompare(order2.startDate)
),
subitems: rawItems.subItems.sort(
(sub1,sub2) => sub1.startDate.localeCompare(sub2.startDate)
),
}
console.log(items)
In the question you repeatedly specify "ascending" order, i.e. small values first, then big values. However the example answer you give is of descending order.
The example answer I have provided does ascending, as you specified. If you meant "descending", then just negate the localeCompare values as follows:
(order1,order2) => -order1.startDate.localeCompare(order2.startDate)
and
(sub1,sub2) => -sub1.startDate.localeCompare(sub2.startDate)
You can modify the Array.prototype.sort method to do just that. Convert your start dates to time in milliseconds and sort based on that. The order in which you specify -1 and 1 will give you ASC or DESC order.
const items = {
Orders: [
{
id: '1',
title: 'Order1',
startDate: "2019-08-13T00:00:00.000Z",
status: 'new',
},
{
id: '2',
title: 'Order2',
startDate: "2020-08-13T00:00:00.000Z",
status: 'done',
}
],
subItems: [
{
Orders: [
{
id: '1',
title: 'subitem-order1',
status: 'new',
startDate: '2019-08-13T00:00:00.000Z',
},
{
id: '2',
title: 'subitem-order2',
status: 'new',
startDate: '2020-08-13T00:00:00.000Z',
}
]
}
]
}
items.Orders.sort((a,b) => {
let TimeA = new Date(a.startDate).getTime();
let TimeB = new Date(b.startDate).getTime();
return TimeA > TimeB ? 1 : TimeA < TimeB ? -1 : 0;
})
items.subItems[0].Orders.sort((a,b) => {
let TimeA = new Date(a.startDate).getTime();
let TimeB = new Date(b.startDate).getTime();
return TimeA > TimeB ? 1 : TimeA < TimeB ? -1 : 0;
})
console.log(items);
I'm trying to remove all items if they match with array values but it's removing only one item. How can i remove all items with filter method or what is the best way to achieve this.
let data = [
{
id: '1',
title: 'ABC'
},
{
id: '2',
title: 'DEF'
},
{
id: '3',
title: 'GHI'
},
{
id: '4',
title: 'JKL'
},
{
id: '5',
title: 'MNO'
}
]
data = data.filter(post => {
let remove = ['2', '4', '5']
for(let i = 0; i < remove.length; i++) {
return post.id !== remove[i]
}
})
console.log(data)
Thanks
you should return false if you want to remove item from array
let data = [
{
id: '1',
title: 'ABC'
},
{
id: '2',
title: 'DEF'
},
{
id: '3',
title: 'GHI'
},
{
id: '4',
title: 'JKL'
},
{
id: '5',
title: 'MNO'
}
]
let remove = ['2', '4', '5']
data = data.filter(post => {
return !remove.includes(post.id);
})
console.log(data)
All the notice are in the snippet's comment
let data = [ { id: '1', title: 'ABC' }, { id: '2', title: 'DEF' }, { id: '3', title: 'GHI' }, { id: '4', title: 'JKL' }, { id: '5', title: 'MNO' } ]
const remove = ['2', '4', '5']
// `indexOf` is from ES5
data = data.filter(post => remove.indexOf(post.id) === -1)
console.log(data)
// `includes` is from ES7
data = data.filter(post => !remove.includes(post.id))
console.log(data)
// this will recreate the array ['2', '4', '5'] 5 times
data = data.filter(post => !['2', '4', '5'].includes(post.id))
console.log(data)
There is no need to use for loop inside of filter.
Instead it is possible to use some method inside of filter. The some method checks whether at least one element satisfies condition inside of provided function. So unnecessary iteration will be avoided:
data.filter(f => !remove.some(s => s == f.id))
An example:
let data = [
{
id: '1',
title: 'ABC'
},
{
id: '2',
title: 'DEF'
},
{
id: '3',
title: 'GHI'
},
{
id: '4',
title: 'JKL'
},
{
id: '5',
title: 'MNO'
}
]
let remove = ['2', '4', '5']
console.log(data.filter(f => !remove.some(s => s == f.id)));
I'll suggest using includes rather then a nested for loop.
You should also move the remove var outside of the loop, so it's not reinitialised every time.
The callback to the filter method is a predicate. If the condition evaluates to true, the current value in the iteration will be returned. In your case, you want to return if the current value is not in the remove array.
let data = [
{
id: '1',
title: 'ABC'
},
{
id: '2',
title: 'DEF'
},
{
id: '3',
title: 'GHI'
},
{
id: '4',
title: 'JKL'
},
{
id: '5',
title: 'MNO'
}
]
const remove = ['2', '4', '5']
data = data.filter(post => {
return !remove.includes(post.id)
})
console.log(data)