I have this hash:
{
a: [1,2],
b: [1,2,3]
}
I need to generate a string like this:
a=1&a=2&b=1&b=2&b=3
How can I solve this problem ? I'm taking a look at lodash but I cant solve it.
Thanks.
I have this hash:
{
a: [1,2],
b: [1,2,3]
}
I need to generate a string like this:
a=1&a=2&b=1&b=2&b=3
How can I solve this problem ? I'm taking a look at lodash but I cant solve it.
Thanks.
Using javascript Object.keys()
, map()
and join()
with ES6 arrow function
var arr = {
a: [1, 2],
b: [1, 2, 3]
};
var res = Object.keys(arr).map(v => arr[v].map(v1 => v + '=' + v1).join('&')).join('&');
document.write(res);
Or without arrow function
var arr = {
a: [1, 2],
b: [1, 2, 3]
};
var res =
// get object keys
Object.keys(arr)
// iterate over object keys and iterate
.map(function(v) {
// iterate over inner array
return arr[v].map(function(v1) {
// generate prefered string and return
return v + '=' + v1
// cconcatenate string array
}).join('&')
// concatenate string array
}).join('&');
document.write(res);
function hashToString(hash) {
var str = '';
for ( prop in hash ) {
if ( !hash.hasOwnProperty(prop) ) continue;
for (var i = 0; i < hash[prop].length; i++) {
str += prop + '=' + hash[prop][i] + '&';
};
}
str = str.slice(0, str.length-1);
return str;
}
Try that out!
You do this with a for ... in
loop. You should be checking hasOwnProperty
so you don't go through unexpected prototype properties.
We'll do that with a regular for
loop because these items are just arrays.
In here, we want to adjust our string:
str += prop + '=' + hash[prop][i] + '&';
This adds our property name (saved as prop
from the for ... in
loop), then the value in that property's array at the given index i
. We'll leave it with a trailing &
that we will remove just outside of the loop.
Use a for in loop to iterate over each property in your hash object, and from there, add each value to the string, like so:
function hashToQueryString(hash) {
var query = '';
for (key in hash) {
for (i=0; i<=key.length; i++) {
query += key+'='+ myJSON[key]+'&';
}
}
//remove the trailing &
query = query.substr(0, query.length -1);
return query;
}
(Keep in mind that you should also be checking that each property in hash contains a valid array, and that you're not accidentally enumerating any properties you don't want)
You could use qs for that. It will also handle all the encoding needed if you happen to go beyond integers.
qs.stringify({
a: [1,2],
b: [1,2,3]
}, { indices: false });
If you have to stay with poor old ES5, and don't want to use another library for a simple task:
var myHash = {
a: [1,2],
b: [1,2,3]
}
var myString = '';
Object.keys(myHash).map(function(key, index) {
myHash[key].map(function(value) {
myString += (myString ? '&' : '') + key + '=' + value;
});
});
I am sure there is a cleaner way, but here is some options with reduce and map.
var obj = {
a: [1,2],
b: [1,2,3]
};
var params = Object.keys(obj).reduce( function (arr, key){
arr.push(key + "=" + obj[key].join("&" + key + "="))
return arr;
}, []).join("&");
or if the values need to be encoded for the querystring
var params = Object.keys(obj).reduce( function (arr, key){
var mapped = obj[key].map( function (val) { return key + "=" + encodeURIComponent(val); }).join("&");
arr.push(mapped)
return arr;
}, []).join("&");
let hash = {
a: [1, 2],
b: [1, 2, 3]
};
let str = '';
for (let key in hash) {
for (let value of hash[key]) {
str += `${key}=${value}&`;
}
}
alert(str.slice(0, -1));
Here is a simple javascript hash one-liner I made named pr2:
function pr2(str){let e=9833;for(let n=0;n<str.length;n++){const r=str.charCodeAt(n);e=43*e^r}return e>>>0}
Though if that is not good enough for your purpose, here is MurMurHash 3:
function murmurhash3_32(str, seed) {
// MurMurHash is better than djb2, djb2 XOR, and FNV hash in speed, security, and collision probability.
// Version 3 is better than version 2
// Javascript implementation of MurMurHash 3
// String must be ASCII only!
// Seed must be positive integer only!
var strLength = str.length;
var remainder = strLength & 3; // strLength % 4
var bytes = strLength - remainder;
var h1 = seed;
var c1 = 0xcc9e2d51;
var c2 = 0x1b873593;
var i = 0;
while (i < bytes) {
var k1 =
(str.charCodeAt(i) & 0xff) |
((str.charCodeAt(++i) & 0xff) << 8) |
((str.charCodeAt(++i) & 0xff) << 16) |
((str.charCodeAt(++i) & 0xff) << 24);
++i;
k1 =
((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) &
0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 =
((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) &
0xffffffff;
h1 ^= k1;
h1 = (h1 << 13) | (h1 >>> 19);
var h1b =
((h1 & 0xffff) * 5 + ((((h1 >>> 16) * 5) & 0xffff) << 16)) & 0xffffffff;
h1 = (h1b & 0xffff) + 0x6b64 + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16);
}
var k1 = 0;
switch (remainder) {
case 3:
k1 ^= (str.charCodeAt(i + 2) & 0xff) << 16;
case 2:
k1 ^= (str.charCodeAt(i + 1) & 0xff) << 8;
case 1:
k1 ^= str.charCodeAt(i) & 0xff;
k1 =
((k1 & 0xffff) * c1 + ((((k1 >>> 16) * c1) & 0xffff) << 16)) &
0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 =
((k1 & 0xffff) * c2 + ((((k1 >>> 16) * c2) & 0xffff) << 16)) &
0xffffffff;
h1 ^= k1;
}
h1 ^= strLength;
h1 ^= h1 >>> 16;
h1 =
((h1 & 0xffff) * 0x85ebca6b +
((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) &
0xffffffff;
h1 ^= h1 >>> 13;
h1 =
((h1 & 0xffff) * 0xc2b2ae35 +
((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16)) &
0xffffffff;
h1 ^= h1 >>> 16;
return h1 >>> 0;
}
// end of function
let string = prompt('string to hash')
let seed = prompt('seed for the hash (positive integer)')
let hashed = murmurhash3_32(string, seed)
console.log('Hashed: ' + hashed)
alert('Hashed: ' + hashed)
If the intent is to convert data to an URL query parameters, note that special URL characters should be URL encoded. JavaScript provides URLSearchParams
to build URL query/search parameters, without worrying about encoding special characters.
const input = {
a: [1, 2],
b: [1, 2, 3],
};
const searchParams = new URLSearchParams();
for (const key in input) {
input[key].forEach(value => searchParams.append(key, value));
}
const desired = searchParams.toString();
console.log(desired);
Note that I use for...in
iteration which iterates all iterable properties on the prototype chain. You could replace this easily if needed, for example with:
for (const [key, values] of Object.entries(input)) {
values.forEach(value => searchParams.append(key, value));
}
Which iterates only the own properties of an object.