str = "books:book1, books:book2, houses:house1, houses:house2, person:james";
I want to convert above string to separate arrays or arrays within an object, something like:
books = ["book1","book2"];
houses = ["house1","house2"];
person = ["james"];
How can I do this in JavaScript?
var string = "books:book1, books:book2, houses:house1, houses:house2, person:james";
var hash = {};
var splitByComma = string.split(',');
function addKeyByVal( key, val ){
if(!hash[key]) hash[key] = [];
hash[key].push(val);
}
for( var s in splitByComma ){
var splitByColon = splitByComma[s].split(":");
addKeyByVal(splitByColon[0], splitByColon[1]);
}
console.log(hash);
You probably want an object, with keys containing the arrays.
var str = "books:book1, books:book2, houses:house1, houses:house2, person:james";
var obj = str.split(',').reduce( (a,b) => { // split the string on comma
var parts = b.trim().split(':'); // split the parts on colon
if (! (parts[0] in a) ) a[parts[0]] = []; // if no key, create an array
a[parts[0]].push(parts[1]); // push the value to the array
return a; // return the object for next iteration
}, {})
console.log(obj)
You can split on ', ' and reduce to an object containing key: []:
const string = "books:book1, books:book2, houses:house1, houses:house2, person:james";
const output = string.split(', ').reduce((obj, cur) => {
let [category, value] = cur.split(':');
if (!Array.isArray(obj[category])) {
obj[category] = [value];
} else {
obj[category].push(value);
}
return obj;
}, {});
console.log(output);
Something like this:
var string = "books:book1, books:book2, houses:house1, houses:house2, person:james";
var books = [];
var houses = [];
var person = [];
string.split(", ").forEach(function(e) {
switch (e.split(":")[0]) {
case "books":
books.push(e.split(":")[1]);
break;
case "houses":
houses.push(e.split(":")[1]);
break;
case "person":
person.push(e.split(":")[1]);
break;
}
});
The code goes like this:
Make three new arrays for books, houses, and person.
Split the string into an array, separating by ,.
Go through each element in the new array and split it into another array, separating by :
If the string on the left is books, houses, or person then append the string on the right to the books, houses, or person arrays, respectively.
This will put create global variables for you leveraging the window, but for the love of god please don't -- just use an object. While this answer is what you asked for, the other answers are what you really want.
var str = "books:book1, books:book2, houses:house1, houses:house2, person:james";
var splitStr = str.split(',');
var i;
var key;
var val;
var temp;
for (i=0; i<splitStr.length; i++) {
temp = splitStr[i].split(':');
key = temp[0].replace(/ /g,'');
val = temp[1];
if (!window[key]) {
window[key] = [];
}
window[key].push(val);
}
console.log(books, houses, person);
First, you can use the split string method twice to break down the data, then to make them into (almost) global variables, you can set them as window properties, however this can be dangerous if the values passed interfere with the existing properties.
var pairs = str.split(", ");
for(var i = 0; i < pairs.length; i++) {
var key = pairs[i].split(":")[0];
var val = pairs[i].split(":")[1];
if(window.hasOwnProperty(key)) {
window[key].push(val);
}
else {
window[key] = [];
window[key].push(val);
}
}
This method is not recommended for cases where the source of the string is unknown, as it directly modifies window properties, some of which may cause unexpected behaviour if overwritten.
RegExp method.
var string = "books:book1, books:book2, houses:house1, houses:house2, person:james",
arr = string.split(', '), obj = {}, res = [];
arr.forEach(function(v){
var array = [],
elem1 = v.match(/\w+(?=:)/),
elem2 = v.match(/(?:)\w+/g)[1];
if (!obj[elem1]){
obj[elem1] = [];
obj[elem1].push(elem2);
} else {
obj[elem1].push(elem2);
}
});
console.log(obj);
Related
I have a string where the object name is separated by dot from the field name as follows:
{\"person.firstName\":\"Ahmed\",\"person.job\":\"Doctor\",\"products.packName\":\"antibiotic\",\"products.packSize\":\"large\"}}";
I want to parse it to look like the json format:
"{\"person\": {\"firstName\":\"Ahmed\",\"job\":\"Doctor\",},\"products\": {\"packName\":\"antibiotic\",\"packSize\":\"large\"}}";
Is there an efficient algorithm for that?
Maybe this is help for you.
var str='{\"person.firstName\":\"Ahmed\",\"person.job\":\"Doctor\",\"products.packName\":\"antibiotic\",\"products.packSize\":\"large\"}';
var newObj={}
var json=JSON.parse(str);
for (i in json) {
var splt=i.split('.');
var key=splt[0];
var subkey=splt[1];
if(!(key in newObj)) {
newObj[key]={};
}
newObj[key][subkey]=json[i];
}
//if you need string use str or not use newObj
var str=JSON.stringify(newObj);
console.log(str);
console.log(newObj);
console.log(newObj.person);
console.log(newObj.person.firstName);
console.log(newObj.person.job);
Assuming left side may have multiple dots
let parsedObj = JSON.parse(<..YOUR STRINGIFIED JSON..>);
let myObj = {};
Object.keys(parsedObj).forEach((key) => {
let val = parsedObj[key];
let subKeys = key.split(".");
let currentRef = myObj;
subKeys.forEach((subKey, idx) => {
if(idx === subKeys.length - 1) {
currentRef[subKey] = val;
} else {
currentRef[subKey] = currentRef[subKey] || {};
currentRef = currentRef[subKey];
}
});
});
let finalString = JSON.stringify(myObj);
P.S. Your string seems to contain an extra } in the end
I want to extract the variables names from a string like this: "foo=valor bar=second", and so on.
To return:
{
foo: "valor",
bar: "second",
...
}
You can use Regex Look Aheads to check for a variable name that is preceded by an = symbol
var str = "foo=valor bar=second";
var varRegex = /\w+(?=(\s)*(\=))/g;
var valueRegex = /(?<=(\=)[\s'"]*)\w+/g;
var varArr = str.match(varRegex);
var valueArr = str.match(valueRegex);
console.log(valueArr);
let obj = {};
for(let i in varArr) {
obj[varArr[i]] = valueArr[i];
}
console.log(obj);
var str = "foo=valor,bar=second";
var obj = {};
str.split(",").forEach(
function(item){
if(item){
var vars = item.split("=");
obj[vars[0]] = vars[1]
}
});
console.log(obj)
Different approach from the previous answer: You can split the string on spaces and then map the result array, splitting on the equal sign to create your object (left side is property, right side is value)
If you need it your specific format you can reduce it to convert the array into one big object with all the values
let a = "foo=valor bar=second"
console.log(a.split(' ').map((i,v) => { return JSON.parse(`{"${i.split('=')[0]}": "${i.split('=')[1]}"}`);}))
let b = a.split(' ').map((i,v) => { return JSON.parse(`{"${i.split('=')[0]}": "${i.split('=')[1]}"}`);})
console.log(b.reduce(function(acc, x) {
for (var key in x) acc[key] = x[key];
return acc;
}));
Not necessarily the quickest answer (in terms of speed of submission), but less regular expressions to maintain and less variables to store.
function toJSON(str) {
const regex = /(\w+)\=(\w+)\s*/g;
let result = {};
let match;
while (match = regex.exec(str)) {
result[match[1]] = match[2];
}
return result;
}
console.log(toJSON("foo=valor bar=second"));
I have got a . (dot) separated string, from which I want to create nested JSON object. The length of the string is not fixed. For example,
var string = 'a.b.c.d';
Then my JSON object should be as following:
a: {
b: {
c:{
d: {
//Some properties here.
}
}
}
}
I've tried following code:
var packageName = "a.b.c.d"
var splitted = packageName.split('.');
var json = {};
for(var i=0;i<splitted.length-1;i++){
json[splitted[i]] = splitted[i+1];
}
But this returns
{
a: 'b',
b: 'c',
c: 'd'
}
But this is not what I want. I've also searched on google and found similar questions, but no solutions answer my problem. For example this.
A good use case for reduce
packageName = "a.b.c.d";
initProps = {hi: 'there'};
obj = packageName.split('.').reduceRight((o, x) => ({[x]: o}), initProps);
console.log(JSON.stringify(obj))
If you find loops easier to work with, a loop could be written concisely as
result = {};
ptr = result;
for (let prop of packageName.split('.'))
ptr = ptr[prop] = {};
You need to create a new object each time and attribute it to the last object created. And it goes until splitted.length, not splitted.length - 1, because you're using <, not <=.
var packageName = "a.b.c.d";
var splitted = packageName.split('.');
var json = {};
var current = json;
for (var i = 0; i < splitted.length; i++) {
current[splitted[i]] = {};
current = current[splitted[i]];
}
console.log(json);
You may use the last splittted part as property for some payload.
I suggest to keep the object reference and use a temporary variable for aceessing an creating a new property, if necessary.
Please avoid the use of JSON for not stringified objects.
var packageName = "a.b.c.d",
splitted = packageName.split('.'),
result = {},
temp = result,
i;
for (i = 0; i < splitted.length - 1; i++) {
temp[splitted[i]] = temp[splitted[i]] || {};
temp = temp[splitted[i]];
}
temp[splitted[i]] = { some: 'data' };
console.log(result);
I want to convert data stored in one variable from an array to an object, then assign that converted data to another variable.
For example, take:
options = ["226:39"];
and convert ["226:39"] to {"226":"39"}, then assign the converted data to the convertedOptions variable.
How would I do that?
While the other answers are correct for the sample value you mentioned in the question, using substring instead of split will handle the case where the value may need to contain a ":" character.
var options = ["226:39", "ratio:226:39"];
var convertedOptions = {};
for(var i = 0; i < options.length; i++){
var separatorIndex = options[i].indexOf(":");
if(separatorIndex > -1) {
var name = options[i].substring(0, separatorIndex);
var value = options[i].substring(separatorIndex + 1, options[i].length);
convertedOptions[name] = value;
}
}
console.log(convertedOptions);
You can split the string using the : separator, create your convertedOptions object, and then assign.
var options = ['226:39'];
var splitOptions = options[0].split(':');
var convertedOptions = {};
convertedOptions[splitOptions[0]] = splitOptions[1];
console.log(convertedOptions);
You can do it by spliting the element of options by ':':
var options = ["226:39"];
convertedOptions = {};
var el = options[0].split(':');
convertedOptions[el[0]] = el[1];
console.log(convertedOptions);
OR:
var options = ["226:39"];
convertedOptions = {};
var [prop, value] = options[0].split(':');
convertedOptions[prop] = value;
console.log(convertedOptions);
OR:
var options = ["226:39"];
var [prop, value] = options[0].split(':');
convertedOptions = { [prop]: value };
console.log(convertedOptions);
You could split the string and map an object for each element of options for a new property.
var options = ["226:39"],
convertedOptions = Object.assign(
...options.map(a => (([k, v]) => ({ [k]: v }))(a.split(':')))
);
console.log(convertedOptions);
Use String#replace to format the string as JSON, and then convert to an object using JSON#parse:
var options = ["226:39"];
var convertedOptions = JSON.parse(options[0].replace(/([^:]+):([^:]+)/, '{"$1":$2}'));
console.log(convertedOptions);
I need to save order in array. A normal array was destroying it, so i found associative array, but with indexes from regexp was sorting records too.
My function is
var myArray = {};
var searchIndex = '';
$("#searchList").find('li').each(function( index ) {
id = $( this ).attr('id');
if(id.match(/search(:?\d+|\w+)/)){
searchIndex = id.match(/search(\d+|\w+)/)[1];
myArray[searchIndex] = "empty";
}
});
This code works well, order are saved.
myArray[id] = "empty";
http://screenshooter.net/100008827/fhbsvjm
But when i want to remove string "search" from id, by regexp, array just sorting indexes...
searchIndex = id.match(/search(\d+|\w+)/)[1];
myArray[searchIndex] = "empty";
http://screenshooter.net/100008827/gmxusyu
But order should be last->7->9->8
JavaScript does not have associative arrays. The plain objects in JavaScript are similar to associative arrays in some ways, but the order of their properties is not guaranteed.
If you want an associative array that preserves the order of items in the order they were added, it is possible to create one from scratch. Here is a fairly simple implementation that provides that functionality:
function AssociativeArray() {
var items = [];
var refs = {};
this.set = function(key, value) {
if (key in refs) {
refs[key].value = value;
} else {
var entry = { key: key, value: value };
items.push(entry);
refs[key] = entry;
}
};
this.get = function(key) {
var entry = refs[key];
return entry && entry.value;
};
this.allItems = function() {
return items.slice();
};
}
var assoc = new AssociativeArray();
assoc.set(7, "hello");
assoc.set(3, "goodbye");
assoc.set("cheer", "yay");
var items = assoc.allItems();
for (var i = 0; i < items.length; i += 1) {
console.log(items[i].key + " - " + items[i].value);
}
console.log("The item with key 7 is: " + assoc.get(7));
The way you would adapt this to your current code is:
var myArray = new AssociativeArray();
$("#searchList").find('li').each(function( index ) {
var id = $( this ).attr('id'),
searchIndex;
if(id.match(/search(:?\d+|\w+)/)){
searchIndex = id.match(/search(\d+|\w+)/)[1];
myArray.set(searchIndex, "empty");
}
});
The first code snippet above shows how to iterate through the array in the order that items were added.