transform json object to an array field - arrays

I want to transform a list of objects with object having this form
{
"idActivite": 1,
"nomActivite": "Accueil des participants autour d’un café viennoiseries",
"descriptionActivite": "",
"lieuActivite": "",
"typeActivite": "",
"horaireDebActivite": 1512028800,
"horaireFinActivite": 1512059388,
"horaireDebSession": 1512030600,
"horaireFinSession": 1512318588,
"nomSession": "",
"isInSession": false
}
to a one like this :
[
"idActivite": 1,
"nomActivite": "Accueil des participants autour d’un café viennoiseries",
"descriptionActivite": "",
"lieuActivite": "",
"typeActivite": "",
"horaireDebActivite": 1512028800,
"horaireFinActivite": 1512059388,
"horaireDebSession": 1512030600,
"horaireFinSession": 1512318588,
"nomSession": "",
"isInSession": false
]
using type script 2.5

Both are theoretically still objects and that isnt the right way to go about it! An array is simply a list of elements with a number index, the example you are giving uses a string to index and thus is still according to the JSON spec an object. If the issue you are having is to iterate through it use this:
for(var key in array){
console.log(array[key]);
}

Assuming you want an array like [ {key, value} ]
let x = { a: 1, b: 2 }
let y = []
// Note the 'in' keyword instead of 'of'
for (const key in x) {
y.push({ key: key, value: x[key] })
}
// Will print [ { key: 'a', value: 1 }, { key: 'b', value: 2 } ]
console.log(y)
Note that this solution scales linearly with the size of the array.

Related

Transform Array of objects of objects into new array of objects in tabular form

Given the sample data, I need to transform whats given and return in tabular form. Here is the sample data. How can I get the output to be what it is below?
var revisions = {
data:[
// row 1
{
cId: {
value: "123456",
oldValue: null
},
revisionDate:{
value: "09/01/2021",
oldValue: "09/21/2021"
},
revisionType:{
value: "UPDATE",
oldValue: "DELETE"
},
revisionNote:{
value: "Some test note 0",
oldValue: "Old revision note 0"
},
financeNo:{
value: "FA1",
oldValue: "FA2"
}
},
// row 2
{
dccId: {
value: "123457",
oldValue: null
},
revisionDate:{
value: "05/01/2021",
oldValue: "09/28/2021"
},
revisionType:{
value: "NEW",
oldValue: "UPDATE"
},
revisionNote:{
value: "Some test note 1",
oldValue: "Old revision note 1"
},
financeNo:{
value: "FA4",
oldValue: "FA5"
},
maintNo:{
value: "MN001",
oldValue: "MN002"
},
isSpare:{
value: 0,
oldValue: 1
}
},
// row 3 ...
]
}
The console output should be:
[
{cId: "123456", revisionDateNew: "09/01/2021", revisionDateOld:"09/21/2021", revisionTypeNew: "UPDATE",revisionTypeOld: "DELETE", revisionNoteNew: "Some test note 0", revisionNoteOld: "Old revision note 0", financeNoNew: "FA1", financeNoOld: "FA2", maintNoNew: "", maintNoOld: "", isSpareNew: "", isSpareOld: ""},
{cId: "123457", revisionDateNew: "05/01/2021", revisionDateOld:"09/28/2021", revisionTypeNew: "NEW", revisionTypeOld: "UPDATE", revisionNoteNew: "Some test note 1", revisionNoteOld: "Old revision note 1", financeNoNew: "FA4", financeNoOld: "FA5", maintNoNew: "MN001", maintNoOld: "MN002", isSpareNew: "0", isSpareOld: "1"},
...
]
So far this is what Ive done but Im stuck on how to not hard code the properties and Im also struggling to figure out the logic needed to assign a 'New' and 'Old' to the current properties and then give those the correct values.
function loopData(revisions: any) {
var newData = revisions.data.map(item => ({
cId: item.cId.value,
revisionDateNew: item.revisionDate.value
}))
console.log(newData)
}
I think what I need is another loop maybe a forEach where I get the keys and then create a new array to push the new fields.
A general function I've used a lot objectMap to map each field in an object to some other data:
/**
* similar to Array.map but for the fields of an object.
* the callback takes the value as first argument and key as second.
* does not support passing object as 3rd argument or thisArg.
*/
export function objectMap<T, V>(obj: T, fn: (val: T[keyof T], key: keyof T) => V) {
// this is one of the cases where the as Record followed by a loop initializing all the keys
// the whole reason this function exists is to have this typesafe outside :)
// eslint-disable-next-line #typescript-eslint/consistent-type-assertions
const newObj = {} as Record<keyof T, V>;
for (const [key, val] of Object.entries(obj)) {
newObj[key as keyof T] = fn(val, key as keyof T);
}
return newObj;
}
With this you can get the correct data structure with this playground
const newData = revisions.data.map(v=>objectMap(v, x=>x?.value))
Note that it doesn't preserve the types completely as we'd need this feature to type this properly in general, you will likely want an interface to denote the type of the output anyway so this probably isn't a problem for you.

How to transform object into array?

I have an object which is dynamically built. I need to get some of the fields of this object (exactly the dynamic ones) and parse them into an array.
In the code below, I need to transform the towers[X] into an array of objects.
{id: "", description: "Teste", towers[1]: true, towers[2]: true,
towers[3]: true, …}
description: "Test"
id: ""
towers[1]: true
towers[2]: true
towers[3]: true
towers[4]: ""
}
I want it to be something like:
{
id: ""
description: "Test",
towers[1]: true //Don't care if it stays here or not, will not use
...
}
And a new array like:
{
[id: 1, value: true],
[id: 2, value: true],
[id: 3, value: true],
[id: 4, value: ""]
}
Just going to guess towers[0] gives back a number, if it does you can do this. This will find all keys that have boolean values and keep them and append them to a object.
const obj = YOUROBJHERE;
Object.keys(obj ).filter((key) => tyepof obj[key] === "boolean").reduce((accum, key) => {
return {...accum, [key]: obj[key]};
}, {})
in case of X=number and obj is the object we want to transform
let result = [];
for (let indx = 1; indx <=x ; i++) {
result.push({value:indx,value: obj['towers'+indx]})
}
If you want to transform your array of object you can do some like:
this.obj=this.obj.map(obj=>{
return {
id:obj.id,
description:obj.description,
towers:Object.keys(obj).filter((key) => key.indexOf('towers') != -1 )
.map((k,index)=>{
return {id:index+1,value:obj[k]}
})
.filter((x:any)=>x.value)
}
})
See that, map allow an "index" (begins by 0)

Removing empty array values on multidimensional array

I want to remove arrays cctype, cctypologycode, and amount when they are empty from array. best way to do it ?
{
"ccInput": [
{
"designSummaryId": 6,
"CCType": "A",
"CCTypologyCode": "A",
"Amount": "1"
},
{
"designSummaryId": 7,
"CCType": "",
"CCTypologyCode": "",
"Amount": ""
},
]
}
ccInput[1] should be removed from the array
If you want to remove some objects from your array, use Array.prototytpe.filter().
You can do it in an immutable way by copying each property of your object using the spread operator and then filter the ccInput property:
const obj = {ccInput:[{designSummaryId:6,CCType:"A",CCTypologyCode:"A",Amount:"1"},{designSummaryId:7,CCType:"",CCTypologyCode:"",Amount:""}]};
const result = { ...obj, ccInput: obj.ccInput.filter(x => x.CCType && x.CCTypologyCode) };
console.log(result);
Or if you want to modify your object in place, simply reassign the ccInput property:
const obj = {ccInput:[{designSummaryId:6,CCType:"A",CCTypologyCode:"A",Amount:"1"},{designSummaryId:7,CCType:"",CCTypologyCode:"",Amount:""}]};
obj.ccInput = obj.ccInput.filter(x => x.CCType && x.CCTypologyCode);
console.log(obj);
I don't know much about TypeScript, but I do know you can set the array to []. However, for those of you looking to get rid of only part of an array but not all of it, the simplest way to do so that I know of is to just set each value to 0 for numbers, '' for characters, "" for Strings, etc.

Mongoose Pull objects by their property values from an array (possibly empty) [duplicate]

Here is array structure
contact: {
phone: [
{
number: "+1786543589455",
place: "New Jersey",
createdAt: ""
}
{
number: "+1986543589455",
place: "Houston",
createdAt: ""
}
]
}
Here I only know the mongo id(_id) and phone number(+1786543589455) and I need to remove that whole corresponding array element from document. i.e zero indexed element in phone array is matched with phone number and need to remove the corresponding array element.
contact: {
phone: [
{
number: "+1986543589455",
place: "Houston",
createdAt: ""
}
]
}
I tried with following update method
collection.update(
{ _id: id, 'contact.phone': '+1786543589455' },
{ $unset: { 'contact.phone.$.number': '+1786543589455'} }
);
But it removes number: +1786543589455 from inner array object, not zero indexed element in phone array. Tried with pull also without a success.
How to remove the array element in mongodb?
Try the following query:
collection.update(
{ _id: id },
{ $pull: { 'contact.phone': { number: '+1786543589455' } } }
);
It will find document with the given _id and remove the phone +1786543589455 from its contact.phone array.
You can use $unset to unset the value in the array (set it to null), but not to remove it completely.
You can simply use $pull to remove a sub-document.
The $pull operator removes from an existing array all instances of a value or values that match a specified condition.
Collection.update({
_id: parentDocumentId
}, {
$pull: {
subDocument: {
_id: SubDocumentId
}
}
});
This will find your parent document against given ID and then will remove the element from subDocument which matched the given criteria.
Read more about pull here.
In Mongoose:
from the document:
To remove a document from a subdocument array we may pass an object
with a matching _id.
contact.phone.pull({ _id: itemId }) // remove
contact.phone.pull(itemId); // this also works
See Leonid Beschastny's answer for the correct answer.
To remove all array elements irrespective of any given id, use this:
collection.update(
{ },
{ $pull: { 'contact.phone': { number: '+1786543589455' } } }
);
To remove all matching array elements from a specific document:
collection.update(
{ _id: id },
{ $pull: { 'contact.phone': { number: '+1786543589455' } } }
);
To remove all matching array elements from all documents:
collection.updateMany(
{ },
{ $pull: { 'contact.phone': { number: '+1786543589455' } } }
);
Given the following document in the profiles collection:
{ _id: 1, votes: [ 3, 5, 6, 7, 7, 8 ] }
The following operation will remove all items from the votes array that are greater than or equal to ($gte) 6:
db.profiles.update( { _id: 1 }, { $pull: { votes: { $gte: 6 } } } )
After the update operation, the document only has values less than 6:
{ _id: 1, votes: [ 3, 5 ] }
If you multiple items the same value, you should use $pullAll instead of $pull.
In the question having a multiple contact numbers the same use this:
collection.update(
{ _id: id },
{ $pullAll: { 'contact.phone': { number: '+1786543589455' } } }
);
it will delete every item that matches that number. in contact phone
Try reading the manual.

Order array by value in NodeJS

I am learning node and now I'm trying to order an array like this:
"lng" : [{
"ES" : 5,
"EN" : 3,
"IT" : 4
}]
(This is a part of a query result in MongoDB), I need to order the array by the number:
"ES" : 5,
"IT" : 4,
"EN" : 3
I used sort() but this function orders the array alphabetically by the first parameter, but I need order by the second, I've tried a lot of things but without result.
Thank you for your help!
JavaScript has no ordered objects, so first you should transform your object to an array of this kind:
[
{ key: "ES", value: 5 },
{ key: "EN", value: 3 },
{ key: "IT", value: 4 }
]
And then sort by the value key.
You can easily do it as follows:
// ("mongoDbResult" is the variable with an object you get from MongoDB)
var result = mongoDbResult.lng;
result = Object.keys(result).map(function (key) {
return { key: key, value: result[key] };
});
And then just sort by the value key:
result.sort(function (a, b) {
return (a.value < b.value) ? -1 : 1;
});
As a result, you should get a sorted array in the result variable.
Thank you Nikita, adding the key and value the sort works perfectly, my problem now is make the query to get the results with specific key and value...
I can get the elements by the KEY:
db.users.find({"lng.key" : "ES"})
Or by the VALUE:
db.users.find({"lng.value" : 5})
But not the both at the same query :/
[EDIT]
I have find the solution, $elemMatch:
db.users.find({lng_array : {$elemMatch:{key:"ES", value:5}}})

Resources