Issues with transforming array data - arrays

I'm trying to transform the following JSON array data structure -
From
[
{
"date": "2019-01-01",
"marks": [
{
"quantity": {
"shoes": 1,
"belt": 2,
"socks": 3
}
}
]
},
{
"date": "2019-01-02",
"marks": [
{
"quantity": {
"shoes": 4,
"belt": 5,
"socks": 6
}
}
]
}
]
To
rows: [
{
values: [ '2019-01-01', 1, 2, 3]
},
{
values: [ '2019-01-02', 4, 5, 6]
}
]
The code that I was able to try so far is this -
function myFunction() {
var response = [
{
"date": "2019-01-01",
"marks": [
{
"quantity": {
"shoes": 1,
"belt": 2,
"socks": 3
}
}
]
},
{
"date": "2019-01-02",
"marks": [
{
"quantity": {
"shoes": 4,
"belt": 5,
"socks": 6
}
}
]
}
];
var transform = response.map(function(dailyMarks) {
var row = [];
Object.keys(response).asArray().forEach(function (field) {
switch (field) {
case 'shoes':
return row.push(dailyMarks.shoes);
case 'belt':
return row.push(dailyMarks.belt);
case 'socks':
return row.push(dailyMarks.socks);
case 'date':
return row.push(dailyMarks.date);
default:
return row.push('');
}
});
return { values: row };
});
Logger.log(transform);
}
However, I'm running into this error -
TypeError: Cannot find function asArray in object 1,2. (line XX, file "Code")
Pretty sure I'm doing something wrong but have not been able to figure out where.
Objective is simply to transform the aforementioned data structure - approach doesn't really matter.
Any help would be highly appreciated! Thanks.

In ES5,
var arr1 = [
{
date: '2019-01-01',
marks: [
{
quantity: {
shoes: 1,
belt: 2,
socks: 3,
},
},
],
},
{
date: '2019-01-02',
marks: [
{
quantity: {
shoes: 4,
belt: 5,
socks: 6,
},
},
],
},
];
var out = [];
arr1.forEach(function(obj) {
obj.marks.forEach(function(mark) {
out.push({
values: [obj.date].concat(
Object.keys(mark.quantity).map(function(key) {
return mark.quantity[key];
})
),
});
});
});
console.log({ rows: out });

You could take an array of keys for the order and flatmap the marks array.
var data = [{ date: "2019-01-01", marks: [{ quantity: { shoes: 1, belt: 2, socks: 3 } }] }, { date: "2019-01-02", marks: [{ quantity: { shoes: 4, belt: 5, socks: 6 } }] }],
keys = ['shoes', 'belt', 'socks'],
rows = data.map(({ date, marks }) =>
({ values: [date, ...marks.flatMap(({ quantity }) => keys.map(k => quantity[k]))] })),
result = { rows };
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

let x = products.map(p=>{
return p.marks.reduce((t,m)=>{
t.push({ values: [p.date, ...Object.entries(m.quantity).map(([key, value]) => value)]})
return t;
},[])
}
).flat(2)
console.log(x)

var list=[{"date":"2019-01-01","marks":[{"quantity":{"shoes":1,"belt":2,"socks":3}}]},{"date":"2019-01-02","marks":[{"quantity":{"shoes":4,"belt":5,"socks":6}}]}];
let result = list.map(( {date, marks} ) => { return {value: [date, ...Object.values(marks[0].quantity)]};});
let wrap = {rows: result};
console.log(wrap);

Related

EDIT-How can I have my specific format using Object.entries?

I have these data from my api (1) and the format I want to have is this one(2), how can I do that in my front-end using Object.entries in REACT, in such a way I can modify my (1) to have (2) please ? I tried but not working...
(1):
{
"myData": [
{
"Peter": 12,
"Donald": 15,
"Huston": 65
}
],
"myOtherData": [
{
"location": "Dublin",
"country":"Irland"
}
]
}
(2):
{
"myData": [
{
"name": "Peter",
"age": "12"
},
{
"name": "Donald",
"age": "15"
},
{
"name": "Huston",
"age": "65"
}
],
"myOtherData": [
{
"location": "Dublin",
"country":"Irland"
}
]
}
I was thinking using destructuration like this :
const d= {myData, myOtherData}
const newData = Object.entries(...)//change myData here ??
Lets be fancy, time to utilise flatMap, array deconstruction and some shortcuts
const a = {
"myData": [{
"Peter": 12,
"Donald": 15,
"Huston": 65
}]
}
console.log({
myData: Object.entries(a.myData[0])
.flatMap(([name, age]) => ({
name,
age
}))
})
const resp = {
"myData": [{
"Peter": 12,
"Donald": 15,
"Huston": 65
}]
}
convertedData = []
for (const person of Object.entries(resp.myData[0])) {
convertedData.push({
name: person[0],
age: person[1]
})
}
const data = {
"myData": [{
"Peter": 12,
"Donald": 15,
"Huston": 65
}]
}
console.log(
Object.entries(data.myData[0])
.reduce( (acc,[name,age])=>acc.concat({name,age}),[] )
)
lets say
var myData = {
"Peter": 12,
"Donald": 15,
"Huston": 65
}
var finalData = Object.entries(myData).map(entry => {
const[key,value] = entry;
return {
name:key,
age:value
}
})
console.log(finalData)

Count the amount of array-childs / items in received nested array in angular, rxjs

I would like to count the amount of array items from a nested array.
I have done this successfully in a not so deeply nested array, and I am curious how I can create a similar outcome with a one level deeper example.
This is how the well-working one goes:
const listId = this.route.snapshot.paramMap.get('listId');
this.listService.getShortlist(listId)
.subscribe(list =>
{this.list = list;
this.showEditlink = this.list.sublistCreators.find(element => element === this.username);
this.itemcount = this.list.shortlistItem.length;
});
}
The itemcount is what I am looking for. This is usable in my template.
Now, another similar component has the length/count one level deeper, this was my attempt at gaining the array-item-count:
getList(): void {
const listId = this.route.snapshot.paramMap.get('listId');
console.log("het list-id = " + listId);
this.listService.getListNo404(listId)
.subscribe((list =>
{this.list = list;
this.itemcount = this.list.sublist.item.length;
})
)
}
Also tried this (among a lot more):
getList(): void {
const listId = this.route.snapshot.paramMap.get('listId');
console.log("het list-id = " + listId);
this.listService.getListNo404(listId)
.subscribe((list =>
{this.list = list;
this.sublist = this.list.sublist
this.itemcount = this.sublist.item.length;
})
)
}
Here I added the this.sublist = this.list.sublist in between. However not able to get this one working.
Can you help me to count the amount of array-items inside 'item'?
Maybe useful to add, below the json I receive from my backend:
In this particular example the outcomes should be 4 and 3.
{
"_id": {
"$oid": "dummy"
},
"listTitle": "dummy",
"listCreator": "dummy",
"sublist": [
{
"subListCreator": "dummy",
"subListAdded": {
"$date": dummy
},
"item": [
{
"positionId": 1,
"itemScore": 3,
"itemTitle": "dummy",
"itemContext": "dummy"
},
{
"positionId": 2,
"itemScore": 2,
"itemTitle": "dummy",
"itemContext": "dummy"
},
{
"positionId": 3,
"itemScore": 1,
"itemTitle": "dummy",
"itemContext": "dummy"
},
{
"positionId": 4,
"itemScore": 1,
"itemTitle": "dummy",
"itemContext": "dummy"
}
]
},
{
"subListCreator": "dummy",
"subListAdded": {
"$date": dummy
},
"item": [
{
"positionId": 1,
"itemScore": 3,
"itemTitle": "dummy"
},
{
"positionId": 2,
"itemScore": 2,
"itemTitle": "dummy",
"itemContext": "dummy"
},
{
"positionId": 3,
"itemScore": 1,
"itemTitle": "dummy"
}
]
}
]
}
Thanks a lot for having a look!
If I understand the problem right, this is something about json and arrays, not about rxjs.
Anyways, again if the understanding is right, the following could be an option.
Let's assume that the myJson constant holds the the json you are providing as example, i.e.
const myJson = {
"_id": {
"$oid": "dummy"
},
.....
}
then a solution could look like this
const subList = myJson.sublist;
const itemList = subList.map((listEl) => listEl.item);
const result = itemList.map((items) => items.length);
What you end up in having in result is an array [4, 3] which is the expected result.
Here a stackblitz example.
I made a small loop to check if we have an Array on key item and if so, we count its length and add it to the sum. If you want any deeper we could introduce recursion on this but I hope this gets you going.
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
itemCount: number;
constructor() {
this.countItems();
}
countItems() {
let count: number = 0;
for (let obj of this.returnObjWithArray(this.target)) {
if (Object.keys(obj).some((key) => key == 'item')) {
console.log('match: ', obj);
console.log('the count:', obj.item.length);
count += obj.item.length;
}
}
console.warn('the sum: ', count);
}
returnObjWithArray(obj: any) {
for (let prop in obj) {
if (Array.isArray(this.target[prop])) {
console.log('the obj with array: ', this.target[prop]);
return this.target[prop];
}
}
}
target = {
_id: {
$oid: 'dummy',
},
listTitle: 'dummy',
listCreator: 'dummy',
sublist: [
{
subListCreator: 'dummy',
subListAdded: {
$date: 'dummy',
},
item: [
{
positionId: 1,
itemScore: 3,
itemTitle: 'dummy',
itemContext: 'dummy',
},
{
positionId: 2,
itemScore: 2,
itemTitle: 'dummy',
itemContext: 'dummy',
},
{
positionId: 3,
itemScore: 1,
itemTitle: 'dummy',
itemContext: 'dummy',
},
{
positionId: 4,
itemScore: 1,
itemTitle: 'dummy',
itemContext: 'dummy',
},
],
},
{
subListCreator: 'dummy',
subListAdded: {
$date: 'dummy',
},
item: [
{
positionId: 1,
itemScore: 3,
itemTitle: 'dummy',
},
{
positionId: 2,
itemScore: 2,
itemTitle: 'dummy',
itemContext: 'dummy',
},
{
positionId: 3,
itemScore: 1,
itemTitle: 'dummy',
},
],
},
],
};
}
console.log()
match:
{subListCreator: "dummy", subListAdded: {…}, item: Array[4]}
the count:
4
match:
{subListCreator: "dummy", subListAdded: {…}, item: Array[3]}
the count:
3
the sum:
7
Here is a working example: https://stackblitz.com/edit/angular-ivy-wpyfox?file=src%2Fapp%2Fapp.component.ts

MongoDB - Geometry object to return the total pairs/points in linear ring

I am trying to write a performance report based on shapefile data I have stored within docs stored in collections.
Here is a sample of data:
The following function works quite well as it returns the amount of bytes for each document - great, however I would also like to know how many points/pairs are stored within each polygon's linear string for each document.
db.getCollection("_collectionName").aggregate([{"$project": {"object_size": { $bsonSize: "$$ROOT" }}}])
This returns the following set of data (sample):
{ _id: ObjectId("5ef7da26ae8659149c97657e"), rootSize: 42215 },
{ _id: ObjectId("5ef7da45ae8659149c97657f"), rootSize: 118574 },
{ _id: ObjectId("5ef7daf1ae8659149c976585"), rootSize: 11886 },
{ _id: ObjectId("5f216685dbef0f7c3339ec03"), rootSize: 43136 },
{ _id: ObjectId("5ef7daa6ae8659149c976582"), rootSize: 40823 },
{ _id: ObjectId("5f3495129861ce45eb4e9728"), rootSize: 394884 },
{ _id: ObjectId("5ef7d7f6ae8659149c97657c"), rootSize: 125309 },
{ _id: ObjectId("5ef7dad6ae8659149c976584"), rootSize: 127447 },
{ _id: ObjectId("5fa56ef26538cd3bddd8389e"), rootSize: 17670 },
{ _id: ObjectId("5fa56ef26538cd3bddd8389f"), rootSize: 11398 },
{ _id: ObjectId("5fa56ef16538cd3bddd8389c"), rootSize: 2415 },
{ _id: ObjectId("5fa56ef36538cd3bddd838ae"), rootSize: 1757 },
{ _id: ObjectId("5fa56ef36538cd3bddd838b0"), rootSize: 4866 },
{ _id: ObjectId("5fa56ef36538cd3bddd838a8"), rootSize: 1510 },
{ _id: ObjectId("5fa56ef26538cd3bddd838a7"), rootSize: 39631 },
{ _id: ObjectId("5fa56ef36538cd3bddd838ab"), rootSize: 3662 },
{ _id: ObjectId("5fa56ef36538cd3bddd838aa"), rootSize: 15844 },
{ _id: ObjectId("5fa56ef16538cd3bddd8389d"), rootSize: 17196 },
{ _id: ObjectId("5fa56ef26538cd3bddd838a3"), rootSize: 34940 },
{ _id: ObjectId("5fa56ef36538cd3bddd838af"), rootSize: 468367 }
Which is great but it does not tell me how many elements are in the array/linear string within geometry.coordinates.
I have tried the following, but no cigar:
db.getCollection("_collectionName").aggregate([{$project: { count: { $size: { "$ifNull": [ "$geometry", [] ] } } } }])
MongoServerError: The argument to $size must be an array, but was of type: object
It comes back with an error, which i understand - so i referenced the coordinates array:
db.getCollection("_collectionName").aggregate([{$project: { count: { $size: { "$ifNull": [ "$geometry.coordinates", [] ] } } } }])
Which, returned the following data, again correct, if you understand GeoJSON files this is normal as this is the top level of the linear ring, sample data:
{ _id: ObjectId("5ef7da26ae8659149c97657e"), count: 1 }
{ _id: ObjectId("5ef7da45ae8659149c97657f"), count: 1 }
{ _id: ObjectId("5ef7daf1ae8659149c976585"), count: 1 }
{ _id: ObjectId("5f216685dbef0f7c3339ec03"), count: 1 }
So I then added the top level array of 0 to my aggregate function:
db.getCollection("_collectionName").aggregate([{$project: { count: { $size: { "$ifNull": [ "$geometry.coordinates.0", [] ] } } } }])
And this is what was returned:
{ _id: ObjectId("5ef7da26ae8659149c97657e"), count: 0 }
{ _id: ObjectId("5ef7da45ae8659149c97657f"), count: 0 }
{ _id: ObjectId("5ef7daf1ae8659149c976585"), count: 0 }
{ _id: ObjectId("5f216685dbef0f7c3339ec03"), count: 0 }
And that is not possible, here is a screenshot from Studio3T software:
Anybody who might be able to help or point me in the right direction please do so....
(I would be very grateful!)
The dot notation won't work on array elements within an aggregation. You'll want to use the $arrayElemAt operator, as follows:
db.getCollection("_aGStbl").aggregate([{
$project: {
count: { $size: { $arrayElemAt: [ "$geometry.coordinates", 0 ]}}
}
}])
To cater for Null values, you can use a $cond, depending on your objective for the output:
INSERT SOME DATA INTO A TESTDB:
db.arrayTest.insertMany([
{ _id: 1, arrayOfArrays: [ [ 1, 2, 3 ], [ 1, 2, 3, 4 ], [ 1, 2, 3, 4, 5, 6, 7 ] ] },
{ _id: 2, arrayOfArrays: [ [ 4, 5 ], [ 5, 6, 7 ] ] },
{ _id: 3, arrayOfArrays: [ [], [] ] },
{ _id: 4, arrayOfArrays: [ [], [], [] ] },
{ _id: 5 }
] )
{ acknowledged: true,
insertedIds: { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 } }
TRY THESE AGGREGATE CALLS:
db.arrayTest.aggregate([{$project: { count: { $size: { "$ifNull": [ { $arrayElemAt: [ "$arrayOfArrays", 0 ] }, [ ] ] } } } } ] )
{ _id: 1, count: 3 }
{ _id: 2, count: 2 }
{ _id: 3, count: 0 }
{ _id: 4, count: 0 }
{ _id: 5, count: 0 }
db.arrayTest.aggregate([{$project: { count: { $cond: { if: {$arrayElemAt: [ "$arrayOfArrays", 0 ]}, then: { $size: { $arrayElemAt: [ "$arrayOfArrays", 0 ] } }, else: null} } } } ] )
{ _id: 1, count: 3 }
{ _id: 2, count: 2 }
{ _id: 3, count: 0 }
{ _id: 4, count: 0 }
{ _id: 5, count: null }

How to do pivoting on MongoDB?

I have this 'Sales' collection and a sample of it looks like this:
[
{cusID: 'a412q39x',
cusCountry: 'MEX',
itemPurchased: 'Toy_A'
},
{cusID: 'r760e11s',
cusCountry: 'USA',
itemPurchased: 'Toy_B'
},
{cusID: 'g723f01z',
cusCountry: 'USA',
itemPurchased: 'Toy_C'
},
{cusID: 'h277p01c',
cusCountry: 'CAN',
itemPurchased: 'Toy_B'
}
]
This is the result I am hoping to achieve.
[
{item: 'Toy_A',
USA: 4,
MEX: 2,
CAN: 1,
BRA: 0
},
{item: 'Toy_B',
USA: 3,
MEX: 0,
CAN: 2,
BRA: 1
}
]
I tried:
{
$group:{_id:{toy:'$itemPurchased', country: $cusCountry'},'cnt':{'$sum': 1}}
}
The result was not what I wanted.
[
{
_id.toy: 'Toy_A',
_id.country: 'BRA',
cnt: 43
},
{
_id.toy: 'Toy_A',
_id.country: 'USA',
cnt: 102
},
{
_id.toy: 'Toy_A',
_id.country: 'JPN',
cnt: 72
},
{
_id.toy: 'Toy_B',
_id.country: 'CAN',
cnt: 32
}
]
I have also experimented with $facet but to no avail. Mongo gurus, please enlighten. Thanks in advance.
Try as below:
db.collection.aggregate([
{
$group: { _id: '$itemPurchased' , items: { $push: { "country" : "$cusCountry", "count": { $sum :1} } } }
},
{
"$project": {
"countryCounts": {
"$arrayToObject": {
"$map": {
"input": "$items",
"as": "item",
"in": {
"k": "$$item.country",
"v": "$$item.count",
}
}
}
}
}
},
{ $replaceRoot: { newRoot: { "$mergeObjects":[ "$countryCounts" , { "item":"$_id"} ] } } }
])
You will get the result like below:
{
"USA" : 1,
"item" : "Toy_C"
},
/* 2 */
{
"USA" : 1,
"CAN" : 1,
"item" : "Toy_B"
},
/* 3 */
{
"MEX" : 1,
"item" : "Toy_A"
}

How to loop array after process groupBy in React-Native

i want to grouping data JSON (One JSON) base on region. and the json after grouping like in (Two JSON). and i use the two JSON for show data (Result JSON). so, how to add loop base on region after grouping, because actually i want to show data in front end like (Result JSON):
==>One JSON
data:[
{id:1,
status: "active",
dataDetail: {
id: 5,
name: tes 1,
region: aaa,
}
},
{id:2,
status: "active",
dataDetail: {
id: 8,
name: tes 2,
region: bbb,
}
},
{id:3,
status: "active",
dataDetail: {
id: 8,
name: tes 3,
region: aaa,
}
}
]
==> Two JSON
aaa: [
{id:1,
status: "active",
dataDetail: {
id: 5,
name: tes 1,
region: aaa,
}
},
{id:3,
status: "active",
dataDetail: {
id: 8,
name: tes 3,
region: aaa,
}
}
],
bbb: [
{id:2,
status: "active",
dataDetail: {
id: 8,
name: tes 2,
region: bbb,
}
},
]
==> Result JSON
aaa:
1
3
bbb:
2
thanks
Using Lodash:
const jsonTwo = _.groupBy(data, instance => instance.dataDetail.region);
const resultJson = _.mapValues(jsonTwo, regionInstances => regionInstances.map(instance => instance.id));
Using plain javascript reduce functions:
const jsonTwo = data.reduce((accumulator, instance) => {
if(!accumulator[instance.dataDetail.region]) {
accumulator[instance.dataDetail.region] = [];
}
accumulator[instance.dataDetail.region].push(instance)
return accumulator;
},{});
const resultJson = data.reduce((accumulator, instance) => {
if(!accumulator[instance.dataDetail.region]) {
accumulator[instance.dataDetail.region] = [];
}
accumulator[instance.dataDetail.region].push(instance.id)
return accumulator;
},{});
var data =
[
{
"id": 1,
"status": "active",
"dataDetail": {
"id": 5,
"name": "tes 1",
"region": "aaa"
}
},
{
"id": 2,
"status": "active",
"dataDetail": {
"id": 8,
"name": "tes 2",
"region": "bbb"
}
},
{
"id": 3,
"status": "active",
"dataDetail": {
"id": 8,
"name": "tes 3",
"region": "aaa"
}
}
];
groups =_.chain(data).groupBy('dataDetail.region');
keys = groups.map( (value, key) => key);
values = groups.map( (value, key) => _.map(value, 'id'));
result = _.zipObject(keys, values);

Resources