i couldn't figure out how can i make the object dynamically - javascript

as you can see i get the "p" array from a html form, and i want to make a dynamic object from the "p" array here
function filter(p){
var obj;
console.log(p);//[ 'Grade', '>','123']
if(p[1]== ">"){p[1]=gt}
obj = {
$and:[
{p[0]: {$p[1]: p[3}}
]
}
return obj;
}
to pass it to this aggregation function:
async function query(DS,filter,q1,q2,q3){
arr.length = 0;
var obj;
var x = [];
var y = [];
var filtered;
const projection = { _id: 0 }; projection[q1] = 1; projection[q2] = 1;
const grouping ={}; grouping[q1]=q1; grouping[q2] = q2;
filtered = await DS.aggregate([
{$project: projection},
{$match: filter}
]).toArray()
}
if(q3 == ""){
for (let i = 0; i < filtered.length; i++) {
obj = filtered[i]
x.push(obj[q1])
y.push(obj[q2])
}
arr.push(x)
arr.push(y)
return arr;
}
i couldn't figure out how can i make the object dynamically.

If you want to generate the objects keys dynamically, you can compute them by using square brackets where the key(s) would go.
For your case, you can replace this:
if(p[1]== ">"){p[1]=gt}
obj = {
$and:[
{p[0]: {$p[1]: p[3}}
]
}
with this:
if (p[1] === ">") { p[1] = 'gt' }
obj = {
$and:[
{
[p[0]]: {
['$' + p[1]]: p[2]
}
}
]
}
and you will get this object as a result (when using your provided input):
{"$and": [
{
"Grade": {
"$gt": "123"
}
}
]
}
Hope that helps!

Related

How can i get key of nested object = used For....in?

Here is my code. How can i get the key of the key-value pair using for loop?
var apartment = {
bedroom: {
area: 20,
bed: {
type: 'twin-bed',
price: 100
}
}
};
The desired output is as follows:
/* desired results :
* bedroom
* area
* bed
* type
* price
*/
Please help
var getKeys = function(obj) {
var keys = [];
Object.keys(obj).forEach(function(key){
keys.push(key);
if(typeof obj[key] == 'object'){
keys = keys.concat(getKeys(obj[key]));
}
})
return keys;
}
Then
var keys = getKeys(apartment);
You can use a simple Regex as follow:
var apartment = {
bedroom: {
area: 20,
bed: {
type: 'twin-bed',
price: 100
}
}
};
let result = [];
let jsonstr = JSON.stringify(apartment);
// {"bedroom":{"area":20,"bed":{"type":"twin-bed","price":100}}}
let regex = /"(\w+)":/g;
jsonstr.replace(regex, function(match,prop){
result.push(prop);
});
console.log(result);
we can easily done by using regex, convert object string and apply regex to extract the particular word
run the snippet for required output
var apartment = {
bedroom: {
area: 20,
bed: {
type: 'twin-bed',
price: 100
}
}
};
apartment = JSON.stringify(apartment);
var re = /(")\w+(")(:)/g;
var match;
do {
match = re.exec(apartment);
if (match) {
console.log(match[0]);
}
} while (match);
regex : /(")\w+(")(:)/g
only extracts key for more click here
do while loop responsible to detect multiple match in the string
You can use a recursive function :
function getKeys(source, dest) {
for (let key in source) {
if (typeof source[key] == 'object') {
dest.push(key)
getKeys(source[key], dest)
} else {
dest.push(key)
}
}
return dest
}
result = []
const apartment = {
bedroom: {
area: 20,
bed: {
type: 'twin-bed',
price: 100
}
}
}
getKeys(apartment, result) // ["bedroom", "area", "bed", "type", "price"]
var inputs = [
{a:1,b:2,c:3}, // Simple object
{a:{b:2,c:3}}, // Simple object with nesting
{a:{a:{b:2,c:3}}}, // Repeated key hiding nesting
{a:[{b:2,c:3}]}, // keys behind array
];
inputs.push(inputs); // reference cycle and array at top
function getKeys(obj) {
var all = {};
var seen = [];
checkValue(obj);
return Object.keys(all);
function checkValue(value) {
if (Array.isArray(value)) return checkArray(value);
if (value instanceof Object) return checkObject(value);
}
function checkArray(array) {
if (seen.indexOf(array) >= 0) return;
seen.push(array);
for (var i = 0, l = array.length; i < l; i++) {
checkValue(array[i]);
}
}
function checkObject(obj) {
if (seen.indexOf(obj) >= 0) return;
seen.push(obj);
var keys = Object.keys(obj);
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
all[key] = true;
checkValue(obj[key]);
}
}
}
var result = inputs.map(getKeys);
console.log(result);

Flatten a nested objects to one dimensional array javascript

I have a nested objects in this structure:
myArray = {
"D": {
"U": {
"A300": "B300",
"A326": "B326",
"A344": "B344",
"A345": "B345"
},
"P": {
"A664": "B664",
"A756": "B756"
}
},
"I": {
"U": {
"A300": "B300",
"A326": "B326"
},
"P": {
"A756": "B756"
}
}
};
I am trying to get the data out of it to be only one dimensional (Flatten). I tried the code below but it doesn't work:
var myNewArray = [].concat.apply([], myArray);
and
var myNewArray = myArray.reduce(function(prev, curr) {
return prev.concat(curr);
});
I want myNewArray to have ["B300","B326","B344","B345","B664","B756"]
You can do something like this:
var myArray = [];
myArray[0] = [];
myArray[0][0] = [];
myArray[0][0][0] = [];
myArray[0][0][1] = [];
myArray[0][1] = [];
myArray[0][1][0] = [];
myArray[0][0][0][0] = "abc1";
myArray[0][0][0][1] = "abc2";
myArray[0][0][1][0] = "abc3";
myArray[0][1][0][1] = "abc4";
myArray[0][1][0][1] = "abc5";
function flat(acc, val){
if(Array.isArray(val)){
acc = acc.concat(val.reduce(flat, []));
}else{
acc.push(val);
}
return acc;
}
var newMyArray = myArray.reduce(flat, []);
console.log(newMyArray);
What this does is to recursively reduce all the inner values that are arrays.
It seems that you're dealing with an object. The previous title of your question and the name of the variable are misleading.
In any case, flattening an object is a very similar process.
var myArray = {"D":{"U":{"A300":"B300","A326":"B326","A344":"B344","A345":"B345"},"P":{"A664":"B664","A756":"B756"}},"I":{"U":{"A300":"B300","A326":"B326"},"P":{"A756":"B756"}}};
function flatObj(obj){
return Object.keys(obj).reduce(function(acc, key){
if(typeof obj[key] === "object"){
acc = acc.concat(flatObj(obj[key]));
}else{
acc.push(obj[key]);
}
return acc;
}, []);
}
var newMyArray = flatObj(myArray);
console.log(newMyArray);
I just wanted to add my 2 cents since I was following this question and working on an answer before I left work. I'm home now so I want to post what I came up with.
const obj = {
x1: {
y1: {
z1: {
h1: 'abc',
h2: 'def'
},
z2: {
h1: 123,
h2: 456
}
}
}
}
const valAll = getPropValuesAll(obj)
console.log(valAll)
function getPropValuesAll(obj, result = []){
for(let k in obj){
if(typeof obj[k] !== 'object'){
result.push(obj[k])
continue
}
getPropValuesAll(obj[k], result)
}
return result
}
It would be easy and safe answer.
var myArray = [["abc1"],[["abc2",,"abc3"]],"abc4",{"r5": "abc5", "r6": "abc6"}];
var myNewArray = [];
function flatten(arr){
if(Array.isArray(arr)){
for(var i = 0, l = arr.length; i < l; ++i){
if(arr[i] !== undefined){
flatten(arr[i])
}
}
} else if (typeof arr === 'object') {
for(var key in arr){
if(arr.hasOwnProperty(key)){
flatten(arr[key])
}
}
} else {
myNewArray.push(arr)
}
}
flatten(myArray)
console.log(myNewArray)

Filter Multidimensional Array

I have my dataset configured as
var x = [
{"phaseName":"Initiation","phaseID":"595e382f1a1e9124d4e2600c"},
{"phaseName":"Execution","phaseID":"595e38321a1e9124d4e2600d"}
]
I want to write some function which give the output of filtered data.
For example
var y ="Initiation"
samplefunction(y)
and i get the whole line of {"phaseName":"Initiation","phaseID":"595e382f1a1e9124d4e2600c"}
Use Array#filter
var x = [{
"phaseName": "Initiation",
"phaseID": "595e382f1a1e9124d4e2600c"
},
{
"phaseName": "Execution",
"phaseID": "595e38321a1e9124d4e2600d"
}
];
function filter(phaseName) {
return x.filter(item => {
return item.phaseName === phaseName;
});
}
console.log(filter('Initiation'));
You can also use a simple for loop:
var x = [{
"phaseName": "Initiation",
"phaseID": "595e382f1a1e9124d4e2600c"
},
{
"phaseName": "Execution",
"phaseID": "595e38321a1e9124d4e2600d"
}
];
var y = "Initiation";
function samplefunction(value) {
var newArr = new Array(); //creating a new array to store the values
for (var i = 0; i < Object.keys(x).length; i++) { //looping through the original array
if (x[i].phaseName == value) {//check if the phase name coresponds with the argument
newArr.push(x[i]); //push the coressponding value to the new array
}
}
return newArr; //return the new array with filtered values
}
var result = samplefunction(y);
console.log(result);
You could test all properties for the wanted value and filter the array.
function filter(array, value) {
return array.filter(function (object) {
return Object.keys(object).some(function (key) {
return object[key] === value;
});
});
}
var data = [{ phaseName: "Initiation", phaseID: "595e382f1a1e9124d4e2600c" }, { phaseName: "Execution", phaseID: "595e38321a1e9124d4e2600d" }];
console.log(filter(data, "Initiation"));

Add or remove element(s) to array

I have an existing array of objects :
existingArray = [
{object1: 'object1'},
{object2: 'object2'}
{object3: 'object3'},
]
I receive a new one :
newArray = [
{object2: 'object2'},
{object3: 'object3'},
{object4: 'object4'}
]
I want only to modify the existing one to get the new one as the result (push+splice)
Here is what I have for now (is there a better way ?)
for (var i = 0; i < newArray.length; i++) {
// loop first to push new elements
var responseToTxt = JSON.stringify(newArray[i]);
var newStatement = false;
for(var j = 0; j < existingArray.length; j++){
var statementToTxt = JSON.stringify(existingArray[j]);
if(statementToTxt === responseToTxt && !newStatement){
newStatement = true;
}
}
if(!newStatement){
statements.push(response[i]);
}
}
var statementsToSplice = [];
for (var i = 0; i < existingArray.length; i++) {
// then loop a second time to split elements not anymore on the new array
var statementToTxt = JSON.stringify(existingArray[i]);
var elementPresent = false;
var element = false;
for(var j = 0; j < newArray.length; j++){
var responseToTxt = JSON.stringify(newArray[j]);
if(responseToTxt === statementToTxt && !elementPresent){
elementPresent = true;
} else {
element = i;
}
}
if(!elementPresent){
statementsToSplice.push(element);
}
}
Then I needed to split multiple times in the array :
existingArray = statementsToSplice.reduceRight(function (arr, it) {
arr.splice(it, 1);
return arr;
}, existingArray.sort(function (a, b) { return b - a }));
Here is the example :
https://jsfiddle.net/docmz22b/
So the final output should always be the new array, but only by push or splice the old one.
In this case, the final outpout will be
existingArray = [
{object2: 'object2'},
{object3: 'object3'}
{object4: 'object4'},
]
The new array could contains multiple new elements and/or deleted elements that is currently in the existingArray
Use shift() and push()
existingArray.shift(); //Removes the first element of the array
existingArray.push({'object4' : 'object4'});
Fiddle
I'm almost 100% sure that there is a better way to do it, but at least this works, feel free to comment any suggestions / optimizations.
existingArray = [
{object1: 'object1'},
{object2: 'object2'},
{object3: 'object3'}
];
newArray = [
{object2: 'object2'},
{object3: 'object3'},
{object4: 'object4'}
];
// Loop all the old values, if is not in the new array, remove it
existingArray.forEach(function(item) {
if(!inArray(item, newArray)) {
var idx = indexOfObjectInArray(item, existingArray);
existingArray.splice(idx, 1);
}
});
// Loop all the new values, if is not in the new array, push it
newArray.forEach(function(item) {
if (!inArray(item, existingArray)) {
existingArray.push(item);
}
});
// Auxiliar functions
function inArray(initialValue, array) {
testValue = JSON.stringify(initialValue);
return array.some(function(item) {
return testValue == JSON.stringify(item);
});
}
function indexOfObjectInArray(initialValue, array) {
var result = -1;
testValue = JSON.stringify(initialValue);
array.forEach(function(item, idx) {
if (testValue == JSON.stringify(item)) {
result = idx;
};
});
return result;
}
Maybe this helps. It features Array.prototype.forEach and Array.prototype.some.
Splice unwanted items
Look if object with same property exist
If yes, then assign new object
Else push the object
var existingArray = [
{ object1: 'object1' },
{ object2: 'object2' },
{ object3: 'object3' },
],
newArray = [
{ object2: 'object22' },
{ object3: 'object33' },
{ object4: 'object44' }
];
function update(base, change) {
var changeKeys = change.map(function (a) { return Object.keys(a)[0]; }),
i = 0;
while (i < base.length) {
if (!~changeKeys.indexOf(Object.keys(base[i])[0])) {
base.splice(i, 1);
continue;
}
i++;
}
change.forEach(function (a) {
var aKey = Object.keys(a)[0];
!base.some(function (b, i, bb) {
if (aKey === Object.keys(b)[0]) {
bb[i] = a; // if that does not work, use bb.splice(i, 1, a);
return true;
}
}) && base.push(a);
});
}
update(existingArray, newArray);
document.write('<pre>' + JSON.stringify(existingArray, 0, 4) + '</pre>');

Javascript Recursion for creating a JSON object

needing some advice on how to do this properly recursively.
Basically what I'm doing, is entering in a bunch of text and it returns it as JSON.
For example:
The text:
q
b
name:rawr
Returns:
[
"q",
"b",
{
"name": "rawr"
}
]
And the following input:
q
b
name:rawr:awesome
Would return (output format is not important):
[
"q",
"b",
{
"name": {
"rawr": "awesome"
}
}
]
How can I modify the following code to allow a recursive way to have objects in objects.
var jsonify = function(input){
var listItems = input, myArray = [], end = [], i, item;
var items = listItems.split('\r\n');
// Loop through all the items
for(i = 0; i < items.length; i++){
item = items[i].split(':');
// If there is a value, then split it to create an object
if(item[1] !== undefined){
var obj = {};
obj[item[0]] = item[1];
end.push(obj);
}
else{
end.push(item[0]);
}
}
// return the results
return end;
};
I don't think recursion is the right approach here, a loop could do that as well:
var itemparts = items[i].split(':');
var value = itemparts.pop();
while (itemparts.length) {
var obj = {};
obj[itemparts.pop()] = value;
value = obj;
}
end.push(value);
Of course, as recursion and loops have equivalent might, you can do the same with a recursive function:
function recurse(parts) {
if (parts.length == 1)
return parts[0];
// else
var obj = {};
obj[parts.shift()] = recurse(parts);
return obj;
}
end.push(recurse(items[i].split(':')));
Here is a solution with recursion:
var data = [];
function createJSON(input) {
var rows = input.split("\n");
for(var i = 0; i < rows.length; i++) {
data.push(createObject(rows[i].split(":")));
}
}
function createObject(array) {
if(array.length === 1) {
return array[0];
} else {
var obj = {};
obj[array[0]] = createObject(array.splice(1));
return obj;
}
}
createJSON("p\nq\nname:rawr:awesome");
console.log(data);

Categories

Resources