Efficiently or more functionally create an object from an array - javascript

Is there a more functional way to create an object in JavaScript programatically without assigning each key individually?
For example, given this array (imagine it comes from an outside data source):
let arr = ['a=1', 'b=2', 'c=3'];
What is an easy way to convert this to an object like so?
let expectedResult = { a: '1', b: '2', c: '3'};
It's clunky to assign a new object and loop over the elements with a for or foreach. It would be nice if there were something akin to map that could yield such a final result.
Imagine you could do this:
arr
.map(item => new KeyValuePair(itemKey, itemValue)) // magically get itemKey/itemValue
.toObjectFromKeyValuePairs();
That'd be it right there. But of course there's no such function built in.

If you're looking for a more functional approach to the code, you could use a library such as Lodash which makes code more succinct.
You could use _.fromPairs to convert pairs of data in arrays to key-value pairs of an object.
const convert = arr => _(arr)
.map(s => _.split(s, '=', 2))
.fromPairs()
.value();
console.log(convert(['a=1', 'b=2', 'c=3']));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

You could use reduce, split and slice:
var arr = ['a=1', 'b=2', 'c=3'];
var out = arr.reduce(
function (output, input) {
if (typeof input === 'string') {
var key = input.split('=',1)[0];
output[key] = input.slice( key.length + 1 );
}
return output;
},
{}
);
I use the second argument of split to make it stop after the first = found. Then using slice on the input (treating it as an array of characters) allows the value to contain the = separator as in the case of a=b=c.
By using slice, the value will always be a string, even if it is an empty one. If you want to have null values you could change the line to:
output[key || null] = input.slice( key.length + 1 ) || null;
The type check for string is present since split throws error on null and undefined.
If you wanted to parse the current page's query string for example, you could do it using the above technique just like this:
function getQueryStringParams() {
var reEncodedSpace = /\+/g;
return location.search.length > 1 // returns false if length is too short
&& location.search.slice( 1 ).split( '&' ).reduce(
( output, input ) => {
if ( input.length ) {
if ( output === false ) output = {};
input = input.replace( reEncodedSpace, ' ' ); //transport decode
let key = input.split( '=', 1 )[ 0 ]; // Get first section as string
let value = decodeURIComponent( input.slice( key.length + 1) ); // rest is value
key = decodeURIComponent( key ); // transport decode
// The standard supports multiple values per key.
// Using 'hasOwnProperty' to detect if key is pressent in output,
// and using it from Object.prototype instead of the output object
// to prevent a key of 'hasOwnProperty' to break the code.
if ( Object.prototype.hasOwnProperty.call( output, key ) ) {
if ( Array.isArray( output[ key ] ) ) {
// Third or more values: add value to array
output[ key ].push( value );
} else {
// Second value of key: convert to array.
output[ key ] = [ output[ key ], value ];
}
} else {
// First value of key: set value as string.
output[ key ] = value;
}
}
return output;
},
false
);
}
The function returns false if the search is empty.

If you're willing to spare having one additional line for declaration, this could work for you. Although using a library like lodash or underscore, as mentioned in other answers would certainly help:
var arr = ['a=1', 'b=2', 'c=3'];
var expectedResult = {};
arr.map(function(value) {
var kv = value.split("=");
expectedResult[kv[0]] = kv[1];
return value
})

Try The Below Code.
let arr = ['a=1', 'b=2', 'c=3'];
let b=arr.toString();
b='{"'+(b.split('=').join('":"').split(',').join('","'))+'"}';
b=$.parseJSON(b);
console.log(b);
You will get the required output.

Related

How to accumulate all values inside a 2D array that share the same field?

I have a 2D array that contains values like this:
var array = [["10/10/2020","1000"],["10/10/2020","300"],["07/10/2020","100"],["07/10/2020","100"],["03/10/2020","100"],["10/10/2020","100"]];
For every nested array that has the same date value (the first element), I want to add up the second value to have something like this:
arrayAdd = [["10/10/2020","1400"],["O7/10/2020","200"],["03/10/2020","100"]]
How can I do this?
var array = [["10/10/2020","1000"],["10/10/2020","300"],["07/10/2020","100"],["07/10/2020","100"],["03/10/2020","100"],["10/10/2020","100"]];
function fromEntries (iterable) {
return [...iterable].reduce((obj, [key, val]) => {
obj[key] = String(obj[key] ? +obj[key] + +val : val)
return obj
}, {})
}
console.log(fromEntries(array))
Step by step:
Create an empty object/map.
Iterate over your array.
Get the first element of each item in the array (date) and check if that key is already in the object.
If it is not, you add it. The value will be the second element (the number).
If it is there already, you increment the value.
Object.entries will turn that object into an array with the shape you want, as you can see below:
const obj = {
"10/10/2020": "1400",
"O7/10/2020": "200",
"03/10/2020": "100",
};
console.log(Object.entries(obj));
.as-console-wrapper {
max-height: 100% !important;
}
This should help you get started.
you can do this
const data = [["10/10/2020","1000"],["10/10/2020","300"],["07/10/2020","100"],["07/10/2020","100"],["03/10/2020","100"],["10/10/2020","100"]];
const result = Object.entries(data.reduce((res, [key, value] ) => {
return {
...res,
[key]: (res[key] || 0) + Number(value)
}
}, {}))
console.log(result)
There are a couple ways to handle this question.
You can either compare the string values of each date to see if they are the same, or you can convert them to date objects and compare them that way. Here's a link to the MDN document that shows how you can get a primitive value for the date.
I'm going to use the string value because, in this case, I'm going to assume that all dates are coming in a consistent format.
let array = [["10/10/2020","1000"],["10/10/2020","300"],["07/10/2020","100"],["07/10/2020","100"],["03/10/2020","100"],["10/10/2020","100"]];
let arrayAdd = []
for (let valuePair of array) {
// grab just the date value
let date = valuePair[0];
// check to see if pair is in arrayAdd
let foundPair = arrayAdd.find(el => el[0] === date)
// will return undefined if nothing found
if (!foundPair) {
// if nothing found, we push the entire value and date pair
arrayAdd.push(valuePair);
} else {
// few things happening here..
// we have to convert each value to number to properly add
// once they're added, we convert that new value back into a string
// and then set the value of the found pair to that new string.
foundPair[1] = (Number(valuePair[1]) +
Number(foundPair[1])).toString();
}
}
console.log(arrayAdd);

Generate a query string from a jQuery array with multiple values for a query var

I wrote the following code which takes an array and converts it into a filter string, the string gets generated but instead of
product_size=123&product_size=456
I want this to be product_size=123+456.
I suspect I need to check if the array key for product_size already exists and then push the second number into it, then generate the filter string.
I have created a keysAlreadyUsed array but I can't figure out how to do this.
Maybe I am over thinking this and some form of string manipulation would suffice.
// Array
arrayTest = [];
arrayTest.push( ['product_size', 123] );
arrayTest.push( ['product_size', 456] );
arrayTest.push( ['product_color', 123] );
// Start filter string and array of keys already used
filterString = '';
keysAlreadyUsed = [];
// Loop the array test
$.each( arrayTest, function( index1, value1 ) {
// If the key has already been set
if( jQuery.inArray( value1[0], keysAlreadyUsed ) ) {
// Push into the existing array key
} else {
// New array we can loop through later with the product_size and the 123, 456 in it.
}
// Populate filter string
filterString += value1[0] + '=' + value1[1] + '&';
// Push the key already used into the keys already used array
keysAlreadyUsed.push( value1[0] );
});
// Output
console.log(filterString);
console.log(keysAlreadyUsed);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
jsFiddle: https://jsfiddle.net/6oxc8umz/2/
Maybe is not the most efficient.
The first call of function reduce for creating a key-value object and the second call for generating the queryString.
let arrayTest = [['product_size', 123], ['product_size', 456] ,['product_color', 123]],
result = Object.entries(arrayTest.reduce((a, [key, value]) => {
if (a[key]) a[key] += `+${String(value)}`;
else a[key] = value;
return a;
}, Object.create(null))).reduce((a, [key, value]) => a + `${key}=${value}&`, "").slice(0, -1);
console.log(result);
First I'd turn the array into an object so you can associate the key to the concatenated values. Because you're using jQuery, you can utilize $.param to format it as you need to.
const arrayTest = [['product_size', 123],['product_size', 456],['product_color', 123]];
const toFilterString = obj => decodeURIComponent($.param(obj));
let params = arrayTest.reduce((output, [key,value]) => {
if (output[key]) output[key] += `+${value}`; //if key exists, concatenate value
else (output[key]) = value; //else, set value
return output;
}, {});
console.log(toFilterString(params));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
If you need the value to be URL-encoded, you can remove decodeURIComponent(...).

How to find Key value from an object based on the value passed

Thanks for your time.
I have the following object in JavaScript:
{
"key1":"value1,value2,value3",
"key2":"value4,value5,value6"
}
Now I want to parse for a specific value and if the value exists, I want to return the key associated with it. Suppose that I am passing 'value3', it should return key1; if passing value5, it should return me key2 and so on.
What is the best way to implement it using Javascript, keeping in mind the execution time. I have tried using sting manipulation functions like indexOf, substr; but not most effective I believe.
TIA.
Here is a slightly different approach that will generate a map where the key is actually the value of your original values object.
The generated map will be a sort of fast lookup. Just to make things clear this solution is efficient as long as you need to do a lot of lookups. For a single, unique lookup this solution is the less efficient, since building the hashmap requires much more time than just looking up for a single value.
However, once the map is ready, acquiring values through keys will be incredibly fast so, if you need to later acquire multiple values, this solution will be more suitable for the use case.
This can be accomplished using Object.entries and Object.values. Further explanations are available in the code below.
The code below (despite not required) will also take care of avoiding indexOf with limit cases like searching 'value9' over 'value9999' which, on a regular string, would actually work with indexOf.
const values = {
"key1":"value1,value2,value3",
"key2":"value4,value5,value6",
"key3":"value444,value129839,value125390", // <-- additional test case.
"key4": "value9" // <-- additional test case.
};
const map = Object.entries(values).reduce((acc, [key, value]) => {
// If the value is invalid, return the accumulator.
if (!value) return acc;
// Otherwise, split by comma and update the accumulator, then return it.
return value.split(',').forEach(value => acc[value] = key), acc;
}, {});
// Once the map is ready, you can easily check if a value is somehow linked to a key:
console.log(map["value444"]); // <-- key 3
console.log(map["value9"]); // <-- key 4
console.log(map["Hello!"]); // undefined
To me, the fastest and most concise way of doing that would be the combination of Array.prototype.find() and String.prototype.includes() thrown against source object entries:
const src={"key1":"value1,value2,value3","key2":"value4,value5,value6"};
const getAkey = (obj, val) => (Object.entries(obj).find(entry => entry[1].split(',').includes(val)) || ['no match'])[0];
console.log(getAkey(src, 'value1'));
console.log(getAkey(src, 'value19'));
p.s. while filter(), or reduce(), or forEach() will run through the entire array, find() stops right at the moment it finds the match, so, if performance matters, I'd stick to the latter
Lodash has a function for this called findKey which takes the object and a function to determine truthiness:
obj = { 'key1': 'value1, value2, value3', 'key2': 'value4,value5,value6' }
_.findKey(obj, val => val.includes('value3'))
# 'key1'
_.findKey(obj, val => val.includes('value5'))
# 'key2'
Based on your search, you can use indexOf after looping through your object.
Here's an old school method:
var obj = {
"key1":"value1,value2,value3",
"key2":"value4,value5,value6"
}
function search (str) {
for (var key in obj) {
var values = obj[key].split(',');
if (values.indexOf(str) !== -1) return key
}
return null;
}
console.log(search('value1'))
console.log(search('value6'))
Or you can use Object.keys() with filter() method and get the index 0 of the returned array.
var obj = {
"key1":"value1,value2,value3",
"key2":"value4,value5,value6"
}
function search (str) {
return Object.keys(obj).filter((key) => {
const values = obj[key].split(',');
if (values.indexOf(str) !== -1) {
return key
}
})[0]
}
console.log(search('value1'))
console.log(search('value6'))
You can try iterating over each value in your object and then splitting the value on each comma, then checking if the value is in the returned array like so:
const myObj = {"key1":"value1,value2,value3","key2":"value4,value5,value6"}
function findKeyByValue(obj, value) {
for (var key in myObj) {
const valuesArray = myObj[key].split(',')
if (valuesArray.includes(value)) {
return key
}
}
}
const key = findKeyByValue(myObj, 'value5') // returns 'key2'
console.log(key)
EDIT: Changed loop for efficiency, and extracted code to function
This should do it. Just uses Object.entries and filters to find the entries that contain the value you're looking for. (Can find more than one object that has the desired value too)
var obj = {
"key1": "value1,value2,value3",
"key2": "value4,value5,value6"
};
var find = 'value2';
var key = Object.entries(obj).filter(([k, v]) => v.split(',').includes(find))[0][0];
console.log(key);
Might want to check the return value of Object.entries(obj).filter((o) => o[1].split(',').includes(find)) before trying to access it, in case it doesn't return anything. Like so:
var obj = {
"key1": "value1,value2,value3",
"key2": "value4,value5,value6"
};
function findKey(objectToSearch, valueToFind) {
var res = Object.entries(objectToSearch).filter(([key, value]) => value.split(',').includes(valueToFind));
if(res.length > 0 && res[0].length > 0) {
return res[0][0];
}
return false;
}
console.log(findKey(obj, 'value5'));
includes can be used to check whether a value is present in an array. Object.keys can be used for iteration and checking for the match.
function findKey(json, searchQuery) {
for (var key of Object.keys(json)) if (json[key].split(',').includes(searchQuery)) return key;
}
const json = {
"key1": "value1,value2,value3",
"key2": "value4,value5,value6"
}
console.log(findKey(json, 'value5'))
Use Object.entries with Array.prototype.filter to get what the desired key.
const data = {
"key1": "value1,value2,value3",
"key2": "value4,value5,value6"
};
const searchStr = 'value3';
const foundProp = Object.entries(data).filter(x => x[1].indexOf(searchStr) !== -1);
let foundKey = '';
if (foundProp && foundProp.length) {
foundKey = foundProp[0][0];
}
console.log(foundKey);

Javascript - map value to keys (reverse object mapping)

I want to reverse the mapping of an object (which might have duplicate values). Example:
const city2country = {
'Amsterdam': 'Netherlands',
'Rotterdam': 'Netherlands',
'Paris': 'France'
};
reverseMapping(city2country) Should output:
{
'Netherlands': ['Amsterdam', 'Rotterdam'],
'France': ['Paris']
}
I've come up with the following, naive solution:
const reverseMapping = (obj) => {
const reversed = {};
Object.keys(obj).forEach((key) => {
reversed[obj[key]] = reversed[obj[key]] || [];
reversed[obj[key]].push(key);
});
return reversed;
};
But I'm pretty sure there is a neater, shorter way, preferably prototyped so I could simply do:
const country2cities = city2country.reverse();
You could use Object.assign, while respecting the given array of the inserted values.
const city2country = { Amsterdam: 'Netherlands', Rotterdam: 'Netherlands', Paris: 'France' };
const reverseMapping = o => Object.keys(o).reduce((r, k) =>
Object.assign(r, { [o[k]]: (r[o[k]] || []).concat(k) }), {})
console.log(reverseMapping(city2country));
There is no such built-in function in JavaScript. Your code looks fine, but given that there are so many edge cases here that could wrong, I'd suggesting using invertBy from lodash, which does exactly what you describe.
Example
var object = { 'a': 1, 'b': 2, 'c': 1 };
_.invertBy(object);
// => { '1': ['a', 'c'], '2': ['b'] }
You can use something like this to get raid of duplicates first :
function removeDuplicates(arr, key) {
if (!(arr instanceof Array) || key && typeof key !== 'string') {
return false;
}
if (key && typeof key === 'string') {
return arr.filter((obj, index, arr) => {
return arr.map(mapObj => mapObj[key]).indexOf(obj[key]) === index;
});
} else {
return arr.filter(function(item, index, arr) {
return arr.indexOf(item) == index;
});
}
}
and then use this to make it reverse :
function reverseMapping(obj){
var ret = {};
for(var key in obj){
ret[obj[key]] = key;
}
return ret;
}
You could try getting an array of values and an array of keys from the current object, and setup a new object to hold the result. Then, as you loop through the array of values -
if the object already has this value as the key, like Netherlands, you create a new array, fetch the already existing value (ex: Rotterdam), and add this and the new value (Amsterdam) to the array, and set up this array as the new value for the Netherlands key.
if the current value doesn't exist in the object, set it up as a new string, ex: France is the key and Paris is the value.
Code -
const city2country = {
'Amsterdam': 'Netherlands',
'Rotterdam': 'Netherlands',
'Paris': 'France',
};
function reverseMapping(obj) {
let values = Object.values(obj);
let keys = Object.keys(obj);
let result = {}
values.forEach((value, index) => {
if(!result.hasOwnProperty(value)) {
// create new entry
result[value] = keys[index];
}
else {
// duplicate property, create array
let temp = [];
// get first value
temp.push(result[value]);
// add second value
temp.push(keys[index]);
// set value
result[value] = temp;
}
});
console.log(result);
return result;
}
reverseMapping(city2country)
The benefit here is - it adjusts to the structure of your current object - Netherlands being the repeated values, gets an array as it's value in the new object, while France gets a string value Paris as it's property. Of course, it should be very easy to change this.
Note - Object.values() might not be supported across older browsers.
You could use reduce to save the declaration line reduce.
Abusing && to check if the map[object[key]] is defined first before using Array.concat.
It's shorter, but is it simpler? Probably not, but a bit of fun ;)
const reverseMapping = (object) =>
Object.keys(object).reduce((map, key) => {
map[object[key]] = map[object[key]] && map[object[key]].concat(key) || [key]
return map;
}, {});
#Nina Scholz answer works well for this exact question. :thumbsup:
But if you don't need to keep both values for the Netherlands key ("Netherlands": ["Amsterdam", "Rotterdam"]), then this is a little bit shorter and simpler to read:
const city2country = { Amsterdam: 'Netherlands', Rotterdam: 'Netherlands', Paris: 'France' };
console.log(
Object.entries(city2country).reduce((obj, item) => (obj[item[1]] = item[0]) && obj, {})
);
// outputs `{Netherlands: "Rotterdam", France: "Paris"}`

How can I get a specific parameter from location.search? [duplicate]

This question already has answers here:
How can I get query string values in JavaScript?
(73 answers)
Closed 4 years ago.
If I had a URL such as
http://localhost/search.php?year=2008
How would I write a JavaScript function to grab the variable year and see if it contains anything?
I know it can be done with location.search but I can’t figure out how it grabs parameters.
You may use window.URL class:
new URL(location.href).searchParams.get('year')
// Returns 2008 for href = "http://localhost/search.php?year=2008".
// Or in two steps:
const params = new URL(location.href).searchParams;
const year = params.get('year');
My favorite way for getting URL params is this approach:
var parseQueryString = function() {
var str = window.location.search;
var objURL = {};
str.replace(
new RegExp( "([^?=&]+)(=([^&]*))?", "g" ),
function( $0, $1, $2, $3 ){
objURL[ $1 ] = $3;
}
);
return objURL;
};
//Example how to use it:
var params = parseQueryString();
alert(params["foo"]);
A non-regex approach, you can simply split by the character '&' and iterate through the key/value pair:
function getParameter(paramName) {
var searchString = window.location.search.substring(1),
i, val, params = searchString.split("&");
for (i=0;i<params.length;i++) {
val = params[i].split("=");
if (val[0] == paramName) {
return val[1];
}
}
return null;
}
2020 EDIT:
Nowadays, in modern browsers you can use the URLSearchParams constructor:
const params = new URLSearchParams('?year=2020&month=02&day=01')
// You can access specific parameters:
console.log(params.get('year'))
console.log(params.get('month'))
// And you can iterate over all parameters
for (const [key, value] of params) {
console.log(`Key: ${key}, Value: ${value}`);
}
This question is old and things have evolved in JavaScript.
You can now do this:
const params = {}
document.location.search.substr(1).split('&').forEach(pair => {
[key, value] = pair.split('=')
params[key] = value
})
and you get params.year that contains 2008.
You would also get other query params in your params object.
Edit: a shorter/cleaner way to do this:
const params = new Map(location.search.slice(1).split('&').map(kv => kv.split('=')))
You can then test if the year param exists with:
params.has('year') // true
Or retrieve it with:
params.get('year') // 2008
Edit 2020
You can convert URL params to an Object:
const params = location.search.slice(1).split('&').reduce((acc, s) => {
const [k, v] = s.split('=')
return Object.assign(acc, {[k]: v})
}, {})
Then it can be used as a regular JS Object:
params.year // 2008
The following uses regular expressions and searches only on the query string portion of the URL.
Most importantly, this method supports normal and array parameters as in
http://localhost/?fiz=zip&foo[]=!!=&bar=7890#hashhashhash
function getQueryParam(param) {
var result = window.location.search.match(
new RegExp("(\\?|&)" + param + "(\\[\\])?=([^&]*)")
);
return result ? result[3] : false;
}
console.log(getQueryParam("fiz"));
console.log(getQueryParam("foo"));
console.log(getQueryParam("bar"));
console.log(getQueryParam("zxcv"));
Output:
zip
!!=
7890
false
It took me a while to find the answer to this question. Most people seem to be suggesting regex solutions. I strongly prefer to use code that is tried and tested as opposed to regex that I or someone else thought up on the fly.
I use the parseUri library available here:
http://stevenlevithan.com/demo/parseuri/js/
It allows you to do exactly what you are asking for:
var uri = 'http://localhost/search.php?year=2008';
var year = uri.queryKey['year'];
// year = '2008'
function gup( name ) {
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return results[1];
}
var year = gup("year"); // returns "2008"
The easiest way is to have
if (document.location.search.indexOf('yourtext=') >= 0) {
// your code
} else {
// what happens?
}
indexOf()
The indexOf(text) function returns
A WHOLE NUMBER BELOW 0 when the text passed in the function is not in whatever variable or string you are looking for - in this case document.location.search.
A WHOLE NUMBER EQUAL TO 0 OR HIGHER when the text passed in the function is in whatever variable or string you are looking for - in this case document.location.search.
I hope this was useful, #gumbo
A Simple One-Line Solution:
let query = Object.assign.apply(null, location.search.slice(1).split('&').map(entry => ({ [entry.split('=')[0]]: entry.split('=')[1] })));
Expanded & Explained:
// define variable
let query;
// fetch source query
query = location.search;
// skip past the '?' delimiter
query = query.slice(1);
// split source query by entry delimiter
query = query.split('&');
// replace each query entry with an object containing the query entry
query = query.map((entry) => {
// get query entry key
let key = entry.split('=')[0];
// get query entry value
let value = entry.split('=')[1];
// define query object
let container = {};
// add query entry to object
container[key] = value;
// return query object
return container;
});
// merge all query objects
query = Object.assign.apply(null, query);
I used a variant of Alex's - but needed to to convert the param appearing multiple times to an array. There seem to be many options. I didn't want rely on another library for something this simple. I suppose one of the other options posted here may be better - I adapted Alex's because of the straight forwardness.
parseQueryString = function() {
var str = window.location.search;
var objURL = {};
// local isArray - defer to underscore, as we are already using the lib
var isArray = _.isArray
str.replace(
new RegExp( "([^?=&]+)(=([^&]*))?", "g" ),
function( $0, $1, $2, $3 ){
if(objURL[ $1 ] && !isArray(objURL[ $1 ])){
// if there parameter occurs more than once, convert to an array on 2nd
var first = objURL[ $1 ]
objURL[ $1 ] = [first, $3]
} else if(objURL[ $1 ] && isArray(objURL[ $1 ])){
// if there parameter occurs more than once, add to array after 2nd
objURL[ $1 ].push($3)
}
else
{
// this is the first instance
objURL[ $1 ] = $3;
}
}
);
return objURL;
};
I played a bit with this problem and at this end I used this:
function getJsonFromUrl() {
return Object.assign(...location.search.substr(1).split("&").map(sliceProperty));
}
Object.assign to transform a list of object into one object
Spread operator ... to transform an array into a list
location.search.substr(1).split("&") to get all parameters as array of properties (foo=bar)
map walk each properties and split them into an array (either call splitProperty or sliceProperty).
splitProperty:
function splitProperty(pair) {
[key, value] = pair.split("=")
return { [key]: decodeURIComponent(value) }
}
Split by =
Deconstruct the array into an array of two elements
Return a new object with the dynamic property syntax
sliceProperty:
function sliceProperty(pair) {
const position = pair.indexOf("="),
key = pair.slice(0, position),
value = pair.slice(position + 1, pair.length);
return { [key]: decodeURIComponent(value) }
}
Set the position of =, key and value
Return a new object with the dynamic property syntax
I think splitProperty is prettier but sliceProperty is faster. Run JsPerf for more information.
Grab the params from location.search with one line:
const params = new Map(this.props.location.search.slice(1).split('&').map(param => param.split('=')))
Then, simply:
if(params.get("year")){
//year exists. do something...
} else {
//year doesn't exist. do something else...
}
ES6 answer:
const parseQueryString = (path = window.location.search) =>
path.slice(1).split('&').reduce((car, cur) => {
const [key, value] = cur.split('=')
return { ...car, [key]: value }
}, {})
for example:
parseQueryString('?foo=bar&foobar=baz')
// => {foo: "bar", foobar: "baz"}
This is what I like to do:
window.location.search
.substr(1)
.split('&')
.reduce(
function(accumulator, currentValue) {
var pair = currentValue
.split('=')
.map(function(value) {
return decodeURIComponent(value);
});
accumulator[pair[0]] = pair[1];
return accumulator;
},
{}
);
Of course you can make it more compact using modern syntax or writing everything into one line...
I leave that up to you.

Categories