Multiple splits into a JSON object? - javascript

Hey guys I'm having a bit of trouble with this one, and I was hoping someone could give me a hand. I am trying to break up strings that follow this format foo.bar::baz into an object that resembles this foo.bar.baz = ''
In PHP I would do this with the following
$obj = New stdClass();
$inp = [
'type1',
'type2',
'type3.sub1::blah1',
'type3.sub2::blah1',
'type4.sub1::blah2',
'type4.sub2::blah2',
'type5.sub1',
];
foreach ($inp AS $v)
{
if (strpos($v, '.'))
{
$b = explode('.', $v);
$obj->$b[0] = '';
if (strpos($b[1], '::') && $c = explode('::', $b[1]))
{
$obj->$b[0]->$c[0]->$c[1] = '';
} else {
$obj->$b[0]->$b[1] = '';
}
} else {
$obj->$v = '';
}
}
print_r($obj);
stdClass Object
(
[type1] =>
[type2] =>
[type3] => stdClass Object
(
[sub2] => stdClass Object
(
[blah1] =>
)
)
[type4] => stdClass Object
(
[sub2] => stdClass Object
(
[blah2] =>
)
)
[type5] => stdClass Object
(
[sub1] =>
)
)
I am currently trying to mimic this in Javascript doing the following, but can't seem to get it to behave
var fieldset = results.fooresult.metadata[0].field;
var namespace = [];
// namespace from meta
for (var k in fieldset) {
if (fieldset.hasOwnProperty(k)) {
var string = fieldset[k]['$']['NAME'];
if (0<string.indexOf('.')) {
var pairs = string.split('.');
if (0<pairs[1].indexOf('::')) {
var value = pairs[1].split("::");
namespace[pairs[0]][value[0]] = value[1];
} else {
namespace[pairs[0]] = pairs[1];
}
} else {
namespace.push(string);
}
}
}
Help would be appreciated

This should work:
var inp = [
'type1',
'type2',
'type3.sub1::blah1',
'type3.sub2::blah1',
'type4.sub1::blah2',
'type4.sub2::blah2',
'type5.sub1'
];
function makeTree(inp) {
var result = {};
var split = inp.map(function (str) {
return str.split(/\.|::/);
});
var walk = function (obj, propList) {
if (propList.length == 1) {
obj[propList[0]] = '';
return;
}
var nextObj = obj[propList[0]] = obj[propList[0]] || {};
propList.shift();
walk(nextObj, propList);
};
split.forEach(walk.bind(null, result));
return result;
}
var out = makeTree(inp);

Related

rewrite an array of letters to numbers using dictionary

examples:
"heLLo" => 0.1.2.2.3
"javAscript" => 0.1.2.1.3.4.5.6.7.8
"hippopotomonstrosesQuippedaliophobia" => 0.1.2.2.3.2.3.4.3.5.3.6.7.4.8.3.7.9.7.10.11.1.2.2.9.12.13.14.1.3.2.0.3.15.1.13
my non-working code:
function wordPattern(word) {
var res = []
var dic = []
var count = 0
var pipa = word.toLowerCase().split("")
for (i=0;i<pipa.length;i++) {
if (!dic.includes(pipa[i])) {
dic.push({key: count, value: pipa[i]});
count ++
}
for (j=0;j<pipa.length;j++) {
res.push(dic.key[pipa[i]])
}
return res.join(".");
}
Thanks in advance
To associate characters to numbers, don't use an array, use an object:
function wordPattern(word) {
const numbersByChar = {};
let i = 0;
return [...word]
.map(char => numbersByChar[char] ?? (numbersByChar[char] = i++))
.join('.');
}
console.log(wordPattern('hello'));
console.log(wordPattern('hippopotomonstrosesquippedaliophobia'));
Or without the concise syntax that you might find more readable
function wordPattern(word) {
const numbersByChar = {};
let i = 0;
return Array.from(word)
.map((char) => {
if (numbersByChar[char] === undefined) {
numbersByChar[char] = i;
i++;
}
return numbersByChar[char];
})
.join('.');
}
console.log(wordPattern('hello'));
console.log(wordPattern('hippopotomonstrosesquippedaliophobia'));
hint 1 is that you can get a letter like: word[index]
so change your code to this:
function wordPattern(word) {
var res = []
var dic = []
var count = 0
for (i=0;i<word.length;i++) {
let dicItem = dic.find(x=>x.value==word[i]);
if(!dicItem) {
dic.push({key: count, value: word[i]});
res.push(count);
count ++;
}
else res.push(dicItem.key);
}
return res.join(".");
}

Array contains only 1 value, so push fails

var user = {};
var usernameList = document.querySelectorAll('.msg.g_bot.bot.private.i ~ .msg .usr');
for (i of usernameList) {
if (i.childNodes[0].nodeName === 'SPAN') {
var theUser = (user[i.childNodes[0].innerHTML] !== undefined) ? user[i.childNodes[0].innerHTML] : user[i.childNodes[0].innerHTML] = {};
var msg = theUser.msg = [];
msg.push(i.nextElementSibling.nextElementSibling.innerHTML);
}
}
The object user.whatever.msg is an array but contains only 1 value. So it's always the last one. In this case push doesn't work, so I can't put all values into that array.
What's wrong with my code?
theUser.msg = []; does create a new array on every iteration. Just like you create a new theUser object only when it doesn't exist already, you should only create the msg array only once.
var users = {};
var usernameList = document.querySelectorAll('.msg.g_bot.bot.private.i ~ .msg .usr');
for (var i of usernameList) {
if (i.firstChild.nodeName === 'SPAN') {
var name = i.firstChild.innerHTML; // should be .textContent probably
var theUser = name in user
? user[name]
: user[name] = { msg: [] };
// ^^^^^^^^^
theUser.msg.push(i.nextElementSibling.nextElementSibling.innerHTML);
}
}
A clearer way of doing it would be to use .reduce:
const user = [...document.querySelectorAll('.msg.g_bot.bot.private.i ~ .msg .usr')]
.reduce((userObj, i) => {
if (i.childNodes[0].nodeName !== 'SPAN') return userObj;
const childHtml = i.childNodes[0].innerHTML;
const theUser = userObj[childHtml] || { msg: [] };
theUser.msg.push(i.nextElementSibling.nextElementSibling.innerHTML)
return userObj;
}, {});
You could modify your code to verify if the array was already created:
var user = {};
var usernameList = document.querySelectorAll('.msg.g_bot.bot.private.i ~ .msg .usr');
for (i of usernameList) {
if (i.childNodes[0].nodeName === 'SPAN') {
var theUser = (user[i.childNodes[0].innerHTML] !== undefined) ? user[i.childNodes[0].innerHTML] : user[i.childNodes[0].innerHTML] = {};
if(theUser.hasOwnProperty(‘msg’) === false) {
theUser.msg = [];
}
theUser.msg.push(i.nextElementSibling.nextElementSibling.innerHTML);
}
}

Decrypt PHP openssl_seal output with JS Forge

I am trying to decrypt my openssl_seal stored values.
My PHP code:
public static function multiEncrypt( string $data, array $publicKeys ) : ?array
{
foreach ($publicKeys as $cert)
{
if (false === openssl_get_publickey( $cert )) {
Log::getInstance()->error('multiEncrypt : invalid pubkey ; ' . openssl_error_string());
return null;
}
}
$encryptedData = null;
$encryptedKeys = [];
$initVector = self::getInitVector( self::SEAL_CIPHER );
$result = openssl_seal(
$data,
$encryptedData,
$encryptedKeys,
$publicKeys,
self::SEAL_CIPHER,
$initVector
);
if (false === $result)
return null;
$encodedData = base64_encode( $encryptedData );
$encodedKeys = [];
foreach ($encryptedKeys as $key) {
$encodedKeys[] = base64_encode($key);
}
return [
'keys' => $encodedKeys,
'data' => $encodedData
];
}
and my client-side code:
function decrypt(privkey, blob, key)
{
var byteKey = forge.pki.privateKeyFromPem(privkey);
var usrPubKey = forge.pki.publicKeyFromPem(publicKey);
//var genPubKey = forge.pki.rsa.setPublicKey(byteKey.n, byteKey.e);
/*if (usrPubKey !== genPubKey) {
error('Your private key does not match the public key we have of you.');
return;
}*/
console.log('Decoding key..');
var decodedKey = atob(key);
console.log('Decrypting key..');
var contractUserKey = byteKey.decrypt(decodedKey);
console.log(contractUserKey);
console.log(contractUserKey.decrypt(blob));
}
However I keep getting 'forge.min.js:4068 Uncaught Error: Encryption block is invalid.'. Is there something I am missing here?

parse string into json in node js express

So, I have some string data displayed in browser using python-node js express.
Data is something like this:
some_logs abcdata_start,ds0,06-01-2016,3,4,5,06-01-2015,8,9,10,05-01-2015,10,11,12,ds1,06-01-2016,32,42,52,06-01-2015,8,9,10,05-01-2015,10,11,12,abcdata_end,some_logs,abcdata_start,ds0,06-01-2016,13,14,15,06-01-2015,18,19,10,05-01-2015,10,11,12,ds1,06-01-2016,33,43,53,06-01-2015,8,9,10,05-01-2015,10,11,12,abcdata_end
I want to convert this data into json such that:
"intervals": {
"06-01-2016": {
"ds0": {
"0": [
3, 4, 5
],
"1": [
13,14,15
]
},
"ds1": {
"0": [
32, 42, 52
],
"1": [
33, 43, 53
]
}
},
"06-01-2015": {
filling values in similar way as above
}
}
I've spent some time on the question and I'm not sure my solution is optimal but it works :
var str = 'some_logs abcdata_start,ds0,06-01-2016,3,4,5,06-01-2015,8,9,10,05-01-2015,10,11,12,ds1,06-01-2016,3,4,5,06-01-2015,8,9,10,05-01-2015,10,11,12,abcdata_end,some_logs,abcdata_start,ds0,06-01-2016,13,14,15,06-01-2015,18,19,10,05-01-2015,10,11,12,ds1,06-01-2016,3,4,5,06-01-2015,8,9,10,05-01-2015,10,11,12,abcdata_end';
var indexes = [];
var ds = {};
str.split(',').forEach((el, i) => {
if (el.includes("start") || el.includes("end"))
indexes.push(i);
});
indexes = indexes.reduce((acc, el, i, arr) => {
if (i % 2 == 0)
acc.push([el, arr[i+1]]);
return acc;
}, []);
indexes.forEach(arr => {
var tmp = str.split(',').slice(arr[0] + 1, arr[1]);
var tmpIndex = "";
tmp.forEach(val => {
if (val.length === 3 && val.includes("ds"))
tmpIndex = val;
else
ds[tmpIndex]
? ds[tmpIndex].push(val)
: ds[tmpIndex] = [val];
});
});
Object.keys(ds).forEach(key => {
var tmpIndex = "";
ds[key] = ds[key].reduce((acc, val) => {
if (val.match(/[0-9]{2}-[0-9]{2}-[0-9]{4}/) !== null)
tmpIndex = val;
else
acc[tmpIndex]
? acc[tmpIndex].push(val)
: acc[tmpIndex] = [val]
return acc;
}, {});
Object.keys(ds[key]).forEach(dateKey => {
ds[key][dateKey] = ds[key][dateKey].reduce((acc, val, i, arr) => {
if (i % 3 == 0)
acc.push([val, arr[i+1], arr[i+2]]);
return acc;
}, [])
});
});
var res = {};
Object.keys(ds).forEach(dsNum => {
Object.keys(ds[dsNum]).forEach(date => {
if (res.hasOwnProperty(date)) {
res[date][dsNum]
? res[date][dsNum].push(ds[dsNum][date])
: res[date][dsNum] = [ds[dsNum][date]];
} else {
res[date] = {[dsNum]: [ds[dsNum][date]]}
}
})
})
Object.keys(res).forEach(date => {
Object.keys(res[date]).forEach(ds => {
res[date][ds] = res[date][ds][0];
})
})
EDIT
Short version, the same, but with a lot of ugly things, tricks and nested ternary :
var str = 'some_logs abcdata_start,ds0,06-01-2016,3,4,5,06-01-2015,8,9,10,05-01-2015,10,11,12,ds1,06-01-2016,32,42,52,06-01-2015,8,9,10,05-01-2015,10,11,12,abcdata_end,some_logs,abcdata_start,ds0,06-01-2016,13,14,15,06-01-2015,18,19,10,05-01-2015,10,11,12,ds1,06-01-2016,33,43,53,06-01-2015,8,9,10,05-01-2015,10,11,12,abcdata_end', indexes = [], ds = {}, res = {};
str.split(',').forEach((el, i) => (el.includes("start") || el.includes("end")) ? indexes.push(i) : null);
indexes = indexes.reduce((acc, el, i, arr) => (i % 2 == 0) ? acc.concat([[el, arr[i+1]]]) : acc, []);
indexes.forEach((arr, tmpIndex = "") => str.split(',').slice(arr[0] + 1, arr[1]).forEach(val => (val.length === 3 && val.includes("ds")) ? tmpIndex = val : ds[tmpIndex] ? ds[tmpIndex].push(val) : ds[tmpIndex] = [val]));
Object.keys(ds).forEach((key, tmpIndex = "") => {
ds[key] = ds[key].reduce((acc, val) => ((val.match(/[0-9]{2}-[0-9]{2}-[0-9]{4}/) !== null) ? tmpIndex = val : acc[tmpIndex] ? acc[tmpIndex].push(val) : acc[tmpIndex] = [val]) == undefined ? acc : acc, {});
Object.keys(ds[key]).forEach(dateKey => ds[key][dateKey] = ds[key][dateKey].reduce((acc, val, i, arr) => (i % 3 == 0) ? acc.concat([[val, arr[i+1], arr[i+2]]]) : acc, []));
});
Object.keys(ds).forEach(dsNum => Object.keys(ds[dsNum]).forEach(date => (res.hasOwnProperty(date)) ? res[date][dsNum] ? res[date][dsNum].push(ds[dsNum][date]) : res[date][dsNum] = [ds[dsNum][date]] : res[date] = {[dsNum]: [ds[dsNum][date]]}));
Object.keys(res).forEach(date => Object.keys(res[date]).forEach(ds => res[date][ds] = res[date][ds][0]));
Hope it helps,
Best regards,
You can use JSON.parse() for converting the json string to JSON
example
var jsonstring = '{'key1':'value1','key2':'value2'}';
var JSondata = JSON.parse(jsonstring);
console.log(JSondata);
and now you can see that your log will be in JSON form
{
'key1':'value1',
'key2':'value2'
}
hope this help u

JavaScript fake dictionaries

I've declared Javascript arrays in such a way that I could then access them by a key, but it was a long time ago, and I've forgotten how I did it.
Basically, I have two fields I want to store, a unique key, and its value. I know there is a way to do it.. something like:
var jsArray = new {key: 'test test', value: 'value value'},
new {key: 'test 2', value: 'value 2'};
and accessed like:
value = jsArray[key]
Can someone remind me?
You can do it in different ways:
var a = {'a':0, 'b':1, 'c':2};
var b = new Array();
b['a'] = 0;
b['b'] = 1;
b['c'] = 2;
var c = new Object();
c.a = 0;
c.b = 1;
c.c = 2;
var myFancyDictionary = {
key: 'value',
anotherKey: 'anotherValue',
youGet: 'the idea'
}
If you are already using Prototype, try using its Hash. If using jQuery, try using Map.
Here is a JavaScript class that provides a simple dictionary.
if( typeof( rp ) == "undefined" ) rp = {};
rp.clientState = new function()
{
this.items = new Object();
this.length = 0;
this.set = function( key, value )
{
if ( ! this.keyExists( key ) )
{
this.length++;
}
this.items[ key ] = value;
}
this.get = function( key )
{
if ( this.keyExists( key ) )
{
return this.items[ key ];
}
}
this.keyExists = function( key )
{
return typeof( this.items[ key ] ) != "undefined";
}
this.remove = function( key )
{
if ( this.keyExists( key ) )
{
delete this.items[ key ];
this.length--;
return true;
}
return false;
}
this.removeAll = function()
{
this.items = null;
this.items = new Object();
this.length = 0;
}
}
Example use:
// Add a value pair.
rp.clientState.set( key, value );
// Fetch a value.
var x = rp.clientState.Get( key );
// Check to see if a key exists.
if ( rp.clientState.keyExists( key )
{
// Do something.
}
// Remove a key.
rp.clientState.remove( key );
// Remove all keys.
rp.clientState.removeAll();

Categories