How to convert a converted string back into an array? - javascript

As far as I know, you can only save strings to local storage. So, I had to write a function so that I could save arrays. If I call console.log(fixA(["string1", [5, [false]], "string2"])); I get an output of "'string1',[5,[false]],'string2'". Here it is:
function fixA(array) {
var toreturn = "";
for (var i = 0; i < array.length; i++) {
if (typeof array[i] === 'object') {
toreturn += "[" + fixA(array[i]) + "]";
} else {
if (typeof array[i] === 'string') {
toreturn += "'" + array[i] + "'";
} else {
toreturn += array[i];
}
}
if (i < array.length - 1) {
toreturn += ",";
}
}
return toreturn;
}
console.log(fixA(["string1", [5, [false]], "string2"]));
The issue now is that I have no clue how to convert it back. I've tried a few things but have always gotten stuck on how I convert the arrays back. This is basically what I've tried:
function fixS(string) {
var toreturn = [];
var temp = string.split(",");
for (var i = 0; i < temp.length; i++) {
// I could run a check here to see if temp[i] starts with "[", but I'm not sure how to tell where the array ends.
// If it is an array, then I'd need to pass everything inside of the array back into fixS, making it recursive.
// The times I tried to do those two things above, I ran into the issue that the commas inside of the sub arrays also split everything, which I don't want (as the recursive function will deal with that).
toreturn.push(temp[i]);
}
return toreturn;
}
console.log(fixS("'string1',[5,[false]],'string2'"));
// This also doesn't return numbers as numbers or booleans as booleans.
Not much there, but it's as far as I've gotten. Any help is appreciated.

Instead of doing your own bespoke solution, unless you have something that can't be represented in JSON (your example can be), use JSON:
On page load:
var data = JSON.parse(localStorage.getItem("data") || "null");
if (!data) {
// There wasn't any, initialize
}
or
var data = JSON.parse(localStorage.getItem("data") || "{}");
...if you want a blank object if there is nothing in local storage.
When saving your data:
localStorage.setItem("data", JSON.stringify(data));

As David said there's JSON.stringify() & JSON.parse();
you can use those methods :
function save_to_storage(id, anything){
localStorage.setItem(id, JSON.stringify(anything));
}
function load_from_storage(id){
return JSON.parse(localStorage.getItem(id));
}

It can be achieved with help of JSON.stringify and JSON.parse functions.
Let me explore with help of code snippet.
var original_arr = ["string1", [5, [false]], "string2"]; // array
// Converting this array into string
var converted_str = JSON.stringify(original_arr); // converted into string
// Converting this string back to array
var new_arr = JSON.parse(converted_str ); // back to array

The other answers have already covered it, but note that P5.js also provides functionality for working, saving, and loading JSON directly.
Take a look at the saveJSON() and loadJSON() functions in the reference.

Related

How to put multiple objects in one array in javascript?

How to put multiple objects in one array in javascript?
I have n json strings like this:
first object
'[{"name":"1","position":{"x":-28.890169060450745,"y":-89.45,"z":103.39384013230637},"property":{"floor":"Platform", "name":"1"}]'
second object
'[{"name":"2","position":{"x":-28.890169060450745,"y":-89.45,"z":103.39384013230637},"property":{"floor":"Platform", "name":"2"}]'
third object
'[{"name":"3","position":{"x":-28.890169060450745,"y":-89.45,"z":103.39384013230637},"property":{"floor":"Platform", "name":"3"}]'
...
nth object
Here I want to put n obejects into one result
like this
'[{"name":"1","position":{"x":-28.890169060450745,"y":-89.45,"z":103.39384013230637},"property":{"floor":"승강장","name":"1"},
[{"name":"2","position":{"x":-28.890169060450745,"y":-89.45,"z":103.39384013230637},"property":{"floor":"승강장","name":"2"}],
[{"name":"3","position":{"x":-28.890169060450745,"y":-89.45,"z":103.39384013230637},"property":{"floor":"승강장","name":"3"}]'
For this, I tried the following, but if I push it, it comes into the Array itself.
for (let i = 0; i < DataList.length; i++) {
if (i == 0) {
mergetData = JSON.parse(DataList[0]);
continue;
} else {
mergetData.push(JSON.parse(DataList[i]));
}
}
I am wondering how can I solve this problem.
Best Regards!
Parse all the JSON arrays, then concatenate them into a single array.
let parsedData = Datalist.map(s => JSON.parse(s));
let mergeData = [].concat(...parsedData);
Your are asking how to put multiple objects in one array but your desired output is the string object. So I'm considering your desired output as the actual question :)
For that you just have to iterate through your DataList and merge values into an string object.
StringObject = ''
for(let i=0; i < DataList.length; i++){
if(i===0)
StringObject += DataList[i]
else
StringObject += ',' + DataList[i]
}
console.log(StringObject)
Or just
StringObject = String(DataList)
console.log(StringObject)

How to remove double quotes from json array in javascript

I have a array :
Var array=[{"name":"May","data1":"1121.0"}]
I want to change it to :
Var array= [{"name":"May","data1":1121.0}]
You can simply check using Number.isNaN with an attempted cast to a number using the + operator. If it returns true then do nothing. If it's false then change the value of the parameter to a cast number.
var array=[{"name":"May","data1":"1121.0"}];
array.forEach(data => {
for(let key in data) Number.isNaN(+data[key]) || (data[key] = +data[key])
});
console.log(array);
Looks like this has been answered before here
I'll summarize;
for(var i = 0; i < objects.length; i++){
var obj = objects[i];
for(var prop in obj){
if(obj.hasOwnProperty(prop) && obj[prop] !== null && !isNaN(obj[prop])){
obj[prop] = +obj[prop];
}
}
}
console.log(JSON.stringify(objects, null, 2));
This does have a bug where 0 becomes null.
You want to convert the value mapped to the "data1" key to be a number instead of a string.
There are many ways to accomplish this in JavaScript, but the best way to do so would be to use Number.parseFloat like so:
var array = [{"name":"May","data1":"1121.0"}];
array[0]["data1"] = Number.parseFloat(array[0]["data1"]);
console.log(array[0]["data1"]); // 1121
If you need to perform this action with multiple objects inside of array, you could do
var array = [{"name":"May","data1":"1121.0"}, {"name":"May","data1":"1532.0"}, etc.] // Note that this is not valid JavaScript
array.map(obj => {obj["data1"] = Number.parseFloat(obj["data1"]); return obj;});
If I understood well, you only want to convert the value of data1, from "1121.0" to 1121.0, in other words from string to number.
To convert only that key (data1), you only need this:
array[0].data1 = parseFloat(array[0].data1)
If that's not what you want, please explain better your question

accessing an object from function arguments [duplicate]

This question already has answers here:
Accessing nested JavaScript objects and arrays by string path
(44 answers)
Closed 7 years ago.
I tried to make it by myself, but I don't know if this is possible
function smth(){
var temp = [];
for(var i = arguments.length -1; i > 2; i-=1){
var temp2 = [];
temp.push(arguments[i]);
temp2.push(temp);
temp = temp2;
console.log(temp);
}
// I need to get array in this form
var something = item['collections']['0']['name'];
}
smth('collection','0','name');
edit:
Okay, maybe I haven't given you enough information.
I've got a JSON object, and I'm making a filter function, and I'd like to make it more reusable because now I have hard-coded item.collections[0].name,
and sometimes I need use item.parameters.name, and I will use it few a more times
$scope.$watch(name, function (newValue, oldValue) {
if (newValue !== oldValue) {
$scope.productsChucks = myFilter(array, function(item) {
//console.log(item['collections']['0']['name']);
if (item.collections[0].name == $scope[compareWith]) {
return item;
}
});
}
});
I think you stated your question completely wrong, IMHO it's a typical XY problem https://meta.stackexchange.com/a/66378
Anyway, based on your edit, what I think you really want is to get some nested properties of an object using a string in form "item.parameters.name".
The simplest way to do this is to use some kind of a helper library, eg. lodash:
_.get(item, 'parameters.name') // returns item.parameters.name
_.get(item, 'collections[0].name') // returns item.collections[0].name
Using that your code will look similar to this:
// path is a string given as the parameter to the filter
if (_.get(item, path) === $scope[compareWith]) {
return item;
}
Your function smth will now take only one argument:
smth('collection[0].name');
More information about lodash can be found here https://lodash.com/docs#get
If you think you don't need whole lodash you can implement this single function by yourself, take a look here https://stackoverflow.com/a/6491621/704894
If you need to access it this way:
var something = item['collections']['0']['name'];
Then it's not an array, but actually an object accessed with index notation. You can do it this way:
function smth() {
var temp = {};
var root = temp;
for (var i = 0; i < arguments.length; i++) {
temp[arguments[i]] = {};
temp = temp[arguments[i]];
}
return root;
}
console.log(JSON.stringify(smth('collection', '0', 'name'), null, 2));

How to compare JSON object structure, compare [{},{},{}] vs {k:v, k2:v2,...}

In my PHP app, for 2 different tools I get 2 json responses but I would like to use the same javascript to handle both.
All I need to do is to compare this structure
data = [
{'k1':'v1'},
{'k2':'v2'},
{'k3':'v3'}
]
with this one:
data = {'k11':'v11', 'k22':'v22', 'k33':'v33'}
this must work for any number of results (they are not suppose to match) and it also needs to work if 1 result is given in any of both cases.
I've already tried
- using data.length (which I thought in the second case would give me 1 array
- data instanceof Array, which is true for both cases (same thing if I do data instanceof Object)
What is the best approach to compare these in javascript?
EDITED: the keys and values of both json are not suppose to match, I only want to compare the structure, or detect one of them without having the other. (array of objects vs object with properties)
The first one is an array of objects; the second is an object with properties.
If you need to do this on the PHP side, just do json_decode($data, true) on the second data structure (the second argument casts it as an array) before output. You may have to play around with it a little to get the structures to line up but it should be pretty straight-forward.
Otherwise, in js -
var data = [
{'k':'v'},
{'k2':'v2'},
{'k3':'v3'}
],
data2 = {'k':'v', 'k2':'v2', 'k3':'v3'},
data3 = [];
for (var x in data2) {
data3.push({x:data2[x]});
}
To check if the received data is in the first format or the second one you may just check if the data is an array or not.
The correct way to do it is as follows:
if( Object.prototype.toString.call( data ) === '[object Array]' )
{
// an array: parse data according to first format
}
else
{
// not an array: parse data according to second format
}
There are several way you can do this. I would flatten the array so that it matches the format of the object:
function Flatten(source) {
if (!source || !source.length || source.length === 0) {
return source;
}
var output = {};
for (var i = 0; i < source.length; i++) {
for (prop in source[i]) {
if (source[i].hasOwnProperty(prop)) {
output[prop] = source[i][prop];
}
}
}
return output;
}
Here's a fiddle
I'm not actually sure what you mean by "compare", but if you want a purely JavaScript solution to finding out if the structures are equivalent, you could use this.
Simple Shallow Solution
function numOwnProperties (obj) {
var i = 0;
for (var key in obj) {
if (obj.hasOwnProperty(key)) { i++; }
}
return i;
}
function areEquivalent (obj, arr) {
var length = arr.length;
if (numOwnProperties(obj) !== length) { return false; }
for (var i = 0; i < length; i++) {
var item = arr[i];
for (var key in item) {
if (item.hasOwnProperty(key) && item[key] !== obj[key]) {
return false;
}
}
}
return true;
};
Usage
data1 = [
{'k':'v'},
{'k2':'v2'},
{'k3':'v3'}
];
data2 = {
'k':'v',
'k2':'v2',
'k3':'v3'
};
console.log(areEquivalent(data2, data1)); // true

How to prepend a string using 'this'

Say I have an array of strings. And I want to prepend each of these strings with a fixed (common) string. I know that in Javascript, strings can be concatenated like strM = str1 + str2 + str3 + ... + strN or strM = concat(str1, str2, str3, ..., strN). Consider this piece of code.
var defImgDirPath = 'res/img/';
$([
'home-icon-dark.png',
'home-icon-light.png'
]).each(function() {
/*
* Prepend each string with defImgDirPath
*/
});
Now I can't do this = defImgDirPath + this; (I was stupid enough to try)
Also, I tried return (defImgDirPath + this); but that wouldn't work either.
I am thinking something along the lines of a function like this.prependString(defImgDirPath); but does such a function exist? If not, how do I write one?
Note: I know it can be done much easily and simply with a for loop too, but what's the fun in that? :)
var defImgDirPath = 'res/img/';
var images = [
'home-icon-dark.png',
'home-icon-light.png'
];
$(images).each(function(idx, val) {
images[idx] = defImgDirPath + val;
});
console.log(images);
In latest standards of javascript (ECMA 5), You can do this without jquery:
var defImgDirPath = 'res/img/';
['home-icon-dark.png','home-icon-light.png'].map(function(i) {
return defImgDirPath + i; });
EDIT : Besides, map function of jquery works similar too.
The problem is that you are changing a copy of the item in the array, so the array will be unaffected.
Loop through the indexes in the array and put the result back in the array:
var arr = [ 'home-icon-dark.png', 'home-icon-light.png' ];
for (var i = 0; i < arr.length; i++) {
arr[i] = defImgDirPath + arr[i];
}
If you really want to use a loop method from jQuery, then you would need to use map, so that you get the result as an array. Note that you need to use the parameters of the callback function, as this is not the item from the array:
arr = $.map(arr, function(str){
return defImgDirPath + str;
});
In Javascript, this always refers to an object (the current context object), so it won't ever be a string, and therefore trying to concatenate it with another string will fail, as you've found.
However, there's no need to use jQuery or objects for what you're doing; you're just prepending a known value to the start of each of an array of strings.
Let's rewrite it using standard Javascript, without the jQuery complications...
var defImgDirPath = 'res/img/';
var images = [
'home-icon-dark.png',
'home-icon-light.png'
];
for(var count=0; count<images.length; count++) {
images[count] = defImgDirPath + images[count];
}
I've put the images array into a variable to make it easier to see what the actual loop code is doing. As you can see, it's a pretty simple loop; no need for jQuery magic here.
hope that helps.
this.prependString(defImgDirPath);
No. Strings are immutable in JavaScript. Concatenation to a new string would be fine, and using .concat it would look like
var newString = defImgDirPath.concat(this); // no static function!
If not existing, how do I write one?
You can't, as assigning object to "this" is impossible.
Instead, you have to assign to a property of the array you're working on (using the static $.each instead of working on a collection):
var arr = [
'home-icon-dark.png',
'home-icon-light.png'
];
$.each(arr, function(i) {
arr[i] = defImgDirPath + this;
});
arr[0] // res/img/home-icon-dark.png
Also I tried return (defImgDirPath + this);
You would need to use map for that, creating a new array:
var arr = $.map([
'home-icon-dark.png',
'home-icon-light.png'
], function(str) {
return defImgDirPath + str;
});
Of course, it might be easier without jQuery at all:
for (var i=0; i<arr.length; i++) {
arr[i] = defImgDirPath + arr[i];
}
And also map is available as a native function (not in outdated browsers):
var arr = [
'home-icon-dark.png',
'home-icon-light.png'
].map(function(str) {
return defImgDirPath + str;
});

Categories