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();