Convert string to object by splitting the string javascript - javascript

I need to convert the full strings to array, object combination.
Example,
let string = {'user-0-residences-0-pincode': 678987};
// Expecting output will be
{
user: [
{
residences: [
{
pincode: 678987
}]
}]
}

As per your requirement, you can try the following code
let string = { "user-0-residences-0-pincode": 678987 };
let output = null, temp;
Object.keys(string)[0]
.split("-0-")
.reverse()
.forEach(val => {
if (output === null) {
output = {};
output[val] = Object.values(string)[0];
} else {
temp = [];
temp.push(output);
output = {}
output[val] = temp;
}
});
console.log(output);

It is not clear what you are doing, but it seems like you are using '-0-' as a delimiter. Work with something like this.
let string = {'user-0-residences-0-pincode': 678987};
let result = []
for (str in string) {
result.push(str.split('-0-'))
}

// Expecting output will be { user: [
{
residences: [
{
pincode: 678987
}]
}] }
Your result does not look right...
I think you wanted to parse a string: "user-0-residences-0-pincode-678987"
You can do so:
var string = "user-0-residences-0-pincode-678987";
var arr = string.split("-");
var result = {};
for (var i = 0; i < arr.length; i+=2) {
result[arr[i]] = arr[i + 1];
}
console.log(result);

Related

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

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!

Javascript Parsing Key Value String to JSON

I'm currently working on trying to create a UDF to split a key value pair string based on web traffic into JSON.
I've managed to get as far as outputting a JSON object but I'd like to be able to dynamically add nested items based on the number of products purchased or viewed based on the index number of the key.
When a product is only viewed, there is always only one product in the string. Only when its a transaction is it more than one but I think it would be good to conform the structure of the json and then identify a purchase or view based on the presence of a transactionid. For example:
Item Purchased:
sessionid=12345&transactionid=555555&product1=apples&productprice1=12&product1qty=1&product2=pears&productprice2=23&product2qty=3&transactionamount=58
The output should look something like this:
[
{
"sessionid":12345,
"transactionid":555555,
"transactionamount":58
},
[
{
"productline":1,
"product":"apples",
"productprice":12,
"productqty":1
},
{
"productline":2,
"product":"pears",
"productprice":23,
"productqty":2
}
]
]
Item Viewed:
sessionid=12345&product1=apples&productprice1=12&product1qty=1&product2=pears&productprice2=23&product2qty=3
[
{
"sessionid":12345,
"transactionid":0,
"transactionamount":0
},
[
{
"productline":1,
"product":"apples",
"productprice":12,
"productqty":1
}
]
]
The result I'll be able to parse from JSON into a conformed table in a SQL table.
What I've tried so far is only parsing the string, but its not ideal to create a table in SQL because the number of purchases can vary:
var string = "sessionid=12345&transactionid=555555&product1=apples&productprice1=12&product1qty=1&product2=pears&productprice2=23&product2qty=3&transactionamount=58";
function splitstring(queryString) {
var dictionary = {};
if (queryString.indexOf('?') === 0) {
queryString = queryString.substr(1);
}
var parts = queryString.split('&');
for (var i = 0; i < parts.length; i++) {
var p = parts[i];
// Step 2: Split Key/Value pair
var keyValuePair = p.split('=');
var key = keyValuePair[0];
var value = keyValuePair[1];
dec_val = decodeURIComponent(value);
final_value = dec_val.replace(/\+/g, ' ');
dictionary[key] = final_value;
}
return (dictionary);
}
console.log(splitstring(string));
Thanks in advance!!!
Feel like this would be less clunky with better param naming conventions, but here's my take...
function parseString(string) {
var string = string || '',
params, param, output, i, l, n, v, k, pk;
params = string.split('&');
output = [{},
[]
];
for (i = 0, l = params.length; i < l; i++) {
param = params[i].split('=');
n = param[0].match(/^product.*?([0-9]+).*/);
v = decodeURIComponent(param[1] || '');
if (n && n[1]) {
k = n[1];
output[1][k] = output[1][k] || {};
output[1][k]['productline'] = k;
pk = n[0].replace(/[0-9]+/, '');
output[1][k][pk] = v;
} else {
output[0][param[0]] = v;
}
}
output[1] = output[1].filter(Boolean);
return output;
}
var string = "sessionid=12345&transactionid=555555&product1=apples&productprice1=12&product1qty=1&product2=pears&productprice2=23&product2qty=3&transactionamount=58";
console.log(parseString(string));
output:
[
{
"sessionid": "12345",
"transactionid": "555555",
"transactionamount": "58"
},
[{
"productline": "1",
"product": "1",
"productprice": "12"
}, {
"productline": "2",
"product": "3",
"productprice": "23"
}]
]
There's probably a far nicer way to do this, but I just wrote code as I thought about it
var string = "sessionid=12345&transactionid=555555&product1=apples&productprice1=12&product1qty=1&product2=pears&productprice2=23&product2qty=3&transactionamount=58";
function splitstring(queryString) {
var dictionary = {};
if (queryString.indexOf('?') === 0) {
queryString = queryString.substr(1);
}
var parts = queryString.split('&');
for (var i = 0; i < parts.length; i++) {
var p = parts[i];
// Step 2: Split Key/Value pair
var keyValuePair = p.split('=');
var key = keyValuePair[0];
var value = keyValuePair[1];
dec_val = decodeURIComponent(value);
final_value = dec_val.replace(/\+/g, ' ');
dictionary[key] = final_value;
}
return (dictionary);
}
function process(obj) {
let i = 1;
const products = [];
while(obj.hasOwnProperty(`product${i}`)) {
products.push({
[`product`]: obj[`product${i}`],
[`productprice`]: obj[`productprice${i}`],
[`productqty`]: obj[`product${i}qty`]
});
delete obj[`product${i}`];
delete obj[`productprice${i}`];
delete obj[`product${i}qty`];
++i;
}
return [obj, products];
}
console.log(process(splitstring(string)));
By the way, if this is in the browser, then splitstring can be "replaced" by
const splitstring = string => Object.fromEntries(new URLSearchParams(string).entries());
var string = "sessionid=12345&transactionid=555555&product1=apples&productprice1=12&product1qty=1&product2=pears&productprice2=23&product2qty=3&transactionamount=58";
function process(string) {
const splitstring = queryString => {
var dictionary = {};
if (queryString.indexOf('?') === 0) {
queryString = queryString.substr(1);
}
var parts = queryString.split('&');
for (var i = 0; i < parts.length; i++) {
var p = parts[i];
// Step 2: Split Key/Value pair
var keyValuePair = p.split('=');
var key = keyValuePair[0];
var value = keyValuePair[1];
dec_val = decodeURIComponent(value);
final_value = dec_val.replace(/\+/g, ' ');
dictionary[key] = final_value;
}
return (dictionary);
};
let i = 1;
const obj = splitstring(string);
const products = [];
while (obj.hasOwnProperty(`product${i}`)) {
products.push({
[`product`]: obj[`product${i}`],
[`productprice`]: obj[`productprice${i}`],
[`productqty`]: obj[`product${i}qty`]
});
delete obj[`product${i}`];
delete obj[`productprice${i}`];
delete obj[`product${i}qty`];
++i;
}
return [obj, products];
}
console.log(process(string));

How to remove duplicate names from array of objects

var arr = [
{level:0,name:"greg"},
{level:0,name:"Math"},
{level:0,name:"greg"}
];
I have tried the following:
function removeDuplicates:(dataObject){
self.dataObjectArr = Object.keys(dataObject).map(function(key){
return dataObject[key];
});
for(var i= 0; i < self.dataObjectArr.length; i++ ){
self.dataObjectArr[i]['name'] = self.dataObjectArr[i];
self.uniqArr = new Array();
for(var key in self.dataObjectArr){
self.uniqArr.push(self.dataObjectArr[key]);
}
}
self.uniqObject = DataMixin.toObject(self.uniqArr);
return self.uniqObject;
}
But I get error saying: Uncaught TypeError: Converting circular structure to JSON.
You should push the name to an array or a set and check the same in the following..
var arr = [{
level: 0,
name: "greg"
}, {
level: 0,
name: "Math"
}, {
level: 0,
name: "greg"
}]
function removeDuplicates(arr) {
var temp = []
return arr.filter(function(el) {
if (temp.indexOf(el.name) < 0) {
temp.push(el.name)
return true
}
})
}
console.log(removeDuplicates(arr))
Here's a generic "uniquify" function:
function uniqBy(a, key) {
var seen = new Set();
return a.filter(item => {
var k = key(item);
return !seen.has(k) && seen.add(k)
});
}
///
var arr = [
{level:0,name:"greg"},
{level:0,name:"greg"},
{level:0,name:"joe"},
{level:0,name:Math},
{level:0,name:"greg"},
{level:0,name:"greg"},
{level:0,name:Math},
{level:0,name:"greg"}
];
uniq = uniqBy(arr, x => x.name);
console.log(uniq);
See here for the in-depth discussion.
I believe you have a syntax error " removeDuplicates:(dataObject){ ..."
should be without the ":" >> " removeDuplicates(dataObject){ ... "
"
You can try this :
function removeDuplicates(arr){
var match={}, newArr=[];
for(var i in arr){ if(!match[arr[i].name]){ match[arr[i].name]=1; var newArr=i; } }
return newArr;
}
arr = removeDuplicates(arr);
You can use $.unique(), $.map(), $.grep()
var arr = [
{level:0,name:"greg"},
{level:0,name:"Math"},
{level:0,name:"greg"}
];
var res = $.map($.unique($.map(arr, el => el.name)), name =>
$.grep(arr, el => el.name === name)[0]);
jsfiddle https://jsfiddle.net/4tex8xhy/3
Or you can use such libraries as underscore or lodash (https://lodash.com/docs/4.16.2). Lodash example:
var arr = [
{level:0,name:"greg"},
{level:0,name:"Math"},
{level:0,name:"greg"}
];
var result = _.map(_.keyBy(arr,'name'));
//result will contain
//[
// {
// "level": 0,
// "name": "greg"
// },
// {
// "level": 0,
// "name": "Math"
// }
//]
Ofc. one thing to always consider in these tasks, what do you want exactly are you going to do: modify an existing array, or get a new one back. This example returns you a new array.

How to convert an array of paths into JSON structure?

I found the question How to convert a file path into treeview?, but I'm not sure how to get the desired result in JavaScript:
I'm trying to turn an array of paths into a JSON tree:
https://jsfiddle.net/tfkdagzv/16/
But my path is being overwritten.
I'm trying to take something like this:
[
'/org/openbmc/path1',
'/org/openbmc/path2',
...
]
... and turn it into...
output = {
org: {
openbmc: {
path1: {},
path2: {}
}
}
}
I'm sure this is pretty easy, but I'm missing something.
const data = [
"/org/openbmc/examples/path0/PythonObj",
"/org/openbmc/UserManager/Group",
"/org/openbmc/HostIpmi/1",
"/org/openbmc/HostServices",
"/org/openbmc/UserManager/Users",
"/org/openbmc/records/events",
"/org/openbmc/examples/path1/SDBusObj",
"/org/openbmc/UserManager/User",
"/org/openbmc/examples/path0/SDBusObj",
"/org/openbmc/examples/path1/PythonObj",
"/org/openbmc/UserManager/Groups",
"/org/openbmc/NetworkManager/Interface"
];
const output = {};
let current;
for (const path of data) {
current = output;
for (const segment of path.split('/')) {
if (segment !== '') {
if (!(segment in current)) {
current[segment] = {};
}
current = current[segment];
}
}
}
console.log(output);
Your solution was close, you just didn't reset the current variable properly. Use this:
current = output;
instead of this:
current = output[path[0]];
This function should do :
var parsePathArray = function() {
var parsed = {};
for(var i = 0; i < paths.length; i++) {
var position = parsed;
var split = paths[i].split('/');
for(var j = 0; j < split.length; j++) {
if(split[j] !== "") {
if(typeof position[split[j]] === 'undefined')
position[split[j]] = {};
position = position[split[j]];
}
}
}
return parsed;
}
Demo
var paths = [
"/org/openbmc/UserManager/Group",
"/org/stackExchange/StackOverflow",
"/org/stackExchange/StackOverflow/Meta",
"/org/stackExchange/Programmers",
"/org/stackExchange/Philosophy",
"/org/stackExchange/Religion/Christianity",
"/org/openbmc/records/events",
"/org/stackExchange/Religion/Hinduism",
"/org/openbmc/HostServices",
"/org/openbmc/UserManager/Users",
"/org/openbmc/records/transactions",
"/org/stackExchange/Religion/Islam",
"/org/openbmc/UserManager/Groups",
"/org/openbmc/NetworkManager/Interface"
];
var parsePathArray = function() {
var parsed = {};
for(var i = 0; i < paths.length; i++) {
var position = parsed;
var split = paths[i].split('/');
for(var j = 0; j < split.length; j++) {
if(split[j] !== "") {
if(typeof position[split[j]] === 'undefined')
position[split[j]] = {};
position = position[split[j]];
}
}
}
return parsed;
}
document.body.innerHTML = '<pre>' +
JSON.stringify(parsePathArray(), null, '\t')
'</pre>';
(see also this Fiddle)
NB: The resulting arrays need to be merged
This method works for both files & directories, and by using only arrays as the data format.
The structure is based upon arrays being folders, the first element being the folder name and the second - the contents array.
Files are just regular strings inside the array (but could easily be objects containing properties)
Converts =>
[
'/home/',
'/home/user/.bashrc',
'/var/',
'/var/test.conf',
'/var/www/',
'/var/www/index.html',
'/var/www/index2.html'
]
To =>
[
['home', [
['user', [
'.bashrc'
]]
]],
['var', [
'test.conf',
['www', [
'index.html',
'index2.html'
]]
]]
]
Script:
var paths = [
'/var/',
'/var/test.conf',
'/var/www/',
'/var/www/index.html',
'/var/www/index2.html'
]
var parsed = []
for (let path of paths) {
let tree = path.split('/')
let previous = parsed
console.groupCollapsed(path)
for (let item in tree) {
const name = tree[item]
const last = item == tree.length - 1
if (name) {
if (last) {
console.log('File:', name)
previous.push(name) - 1
} else {
console.log('Folder:', name)
let i = previous.push([name, []]) - 1
previous = previous[i][1]
}
}
}
console.groupEnd(path)
}
console.warn(JSON.stringify(parsed))

Convert dot notation json

ive got a json object like this:
{
"c.employees": "222",
" c.arr[0].name": "thomas",
" c.arr[0].amount": 3,
}
I want to convert it to object like
{
c:{
employees:"222",
arr:[{name:thomas,amount:3}]
}
}
cant find any solution :/ The array is the problem
There's no short solution, you need to parse all keys and build the intermediate objects and arrays. As this isn't trivial, here's the code :
var input = {
"c.employees": "222",
" c.arr[0].name": "thomas",
" c.arr[0].amount": 3,
};
var output = {};
for (var key in input) {
var tokens = key.trim().split('.'),
obj = output;
for (var i=0; i<tokens.length-1; i++) {
var m = tokens[i].match(/^(\w+)\[(\d+)\]$/); // array ?
if (m) {
var arr = obj[m[1]];
if (!arr) arr = obj[m[1]] = [];
obj = arr[m[2]] = arr[m[2]]||{};
} else {
obj = obj[tokens[i]] = obj[tokens[i]]||{};
}
}
obj[tokens[i]] = input[key];
}
console.log(output);
demo (open the console)

Categories

Resources