JavaScript: Push to Array with unknown key names - javascript

I have a small program that returns JSON which I'm then interrogating before pushing it into an array.
An example of the data is as follows:
id=1|owner=Vina San Pedro|brandName=1865 Chilean Wine|variantName=1865 Chilean Wine|quality=Standard|minorRegionName=Nordic Countries|vol02=0|vol07=0|vol08=4.25|vol09=4.25|vol10=0|
I can iterate the above string, pushing the values into the array, but how can I 'name' the key in the array based on the field name from JSON, considering that items such as "Vol02", "Vol07" may be marked as "val02", "val07", or "minorRegionName" can in some cases by "majorRegionName".
edit
var finalSplit = brandDataRow.split('|');
$.each(finalSplit, function (x, y) {
var v = y.split('=');
$.each(v, function (m, n) {
formattedBrandData.push({ m: m }, { n: n });
});
});
In the above example, if my | delimiterred string contains "Owner=??????|Value=????????|Brand=???????" then when I push this into an array, I want the keys to be "Owner", "Value" and "Brand".
BUT, I don't know the key names until after I've returned the data, so sometimes the | delimitered string could be "Owner=??????|Line=???????|Region=??????"

Try this:
var data = "id=1|owner=Vina San Pedro|brandName=1865 Chilean Wine|variantName=1865 Chilean Wine|quality=Standard|minorRegionName=Nordic Countries|vol02=0|vol07=0|vol08=4.25|vol09=4.25|vol10=0|";
var keyVal = data.split("|");
var res = {};
for(var i =0; i< keyVal.length; i++) {
var tmp = keyVal[i].split("=")
res[tmp[0]] = tmp[1];
}
console.log(res);
Yes, it will return an object, but array can contain only numerical indexes. And in most cases you can work with object the same way as with array. Besides, see no reason to use $.each for such a simple task. Just an additional code to execute.
JSFiddle demo - see console output

First off: you're not looking for an array, but an object. JS Arrays are actually objects in drag, but that's not the point; JS doesn't have associative arrays, only objects. But to answer your question: IMO, the easiest (and, I suspect, quickest) way you can convert your string to an object is by converting it to valid JSON:
var str = 'id=1|owner=Vina San Pedro|brandName=1865 Chilean Wine|variantName=1865 Chilean Wine|quality=Standard|minorRegionName=Nordic Countries|vol02=0|vol07=0|vol08=4.25|vol09=4.25|vol10=0|';
var obj = JSON.parse('{"'+str.substring(0,str.length-1).replace(/(=|\|)/g,function(s1,s2)
{
return '"'+(s2 === '=' ? ':' : ',')+'"';
})+'"}');
This is the dense version, if we break it down:
str.substring(0,str.length-1);//leave out trailing pipe (|)
//if the pipe is not always there:
str = str.substr(-1) === '|' ? str.substring(0,str.length-1) : str;
Then replace all = and |:
str = str.replace(/(=|\|)/g,function(s1,s2)
{//s1 will be the entire matched substring, s2 the first group, not required in this case, but just so you know
return '"'+(s2 === '=' ? ':' : ',') + '"';
});//pipes become comma's, = becomes colon
We're almost there now, the returned string will be id":"1","owner":"Vina San Pedro","brandName":"1865 Chilean Wine","variantName":"1865 Chilean Wine","quality":"Standard","minorRegionName":"Nordic Countries","vol02":"0","vol07":"0","vol08":"4.25","vol09":"4.25","vol10":"0. As you can see, all we need to add are the opening and closing curly's, and a double quote at the beginning and end of the string, and we end up with valid JSON:
var obj = JSON.parse('{"'+str+'"}');//returns object
//is the same as:
obj = { brandName: "1865 Chilean Wine",
id: "1",
minorRegionName: "Nordic Countries",
owner: "Vina San Pedro",
quality: "Standard",
variantName: "1865 Chilean Wine",
vol02: "0",
vol07: "0",
vol08: "4.25",
vol09: "4.25",
vol10: "0"};
From then on:
console.log(obj.id);//logs 1
console.log(obj.owner);//logs 'Vina San Pedro'
console.log(obj['brandName']);//string access: logs "1865 Chilean Wine"
//etc...
This code is tested and working

You can use string to name the key.
Eg.
var sample = new Array();
sample["bob"] = 123;
sample.bob; //returns 123
Hope it helps.

Related

Array values to a string in loop

I have an object (key value pair) looks like this
I want to get a string of '[100000025]/[100000013]'
I can't use var str = OBJ[0].PC + OBJ[1].PC (which gives me '100000025100000013')
because I need the bracket structure.
The number of items can vary.
Added >> Can it be done without using arrow function?
const string = array.map(({PC}) => `[${PC}]`).join('/')
You could map every string to the string wrapped in brackets, then join that by slashes.
You can use a map() and a join() to get that structure. - this is hte same solution as Puwka's = but without the template literal.
var data = [
{am: 1, ct: "", pc: "1000000025"},
{am: 2, ct: "", pc: "1000000013"}
];
let newArr = data.map(item => "[" + item.pc +"]");
console.log(newArr.join("/")); // gives [1000000025]/[1000000013]
You can always use classic for in loop
let arr = [{PC:'1000'},{PC:'10000'}]
let arrOut = [];
for(let i = 0; i < arr.length; i++) {
arrOut.push('[' + arr[i].PC + ']');
}
now the arrOut is equal ["[1000]", "[10000]"] what we need is to convert it to a string and add '/' between items.
let str = arrOut.join('/');
console.log(str) // "[1000]/[10000]"
So you need a string in the format of: xxxx/yyyyy from a complex object array.
const basedata = [...];
const result = basedata.map( item => `[${item.PC}]` ).join('/')
so i will explain it now. The map function will return a new array with 1 entry per item. I state that I want PC, but i added some flavor using ticks to inject it inbetween some brackets. At this point it looks like: ["[1000000025]","[100000013]"] and then join will join the arrays on a slash, so it will turn into an array.
"[100000025]/[100000013]"
Now, this will expand based on the items in your basedata. So if you have 3 items in your basedata array, it would return:
"[10000000025]/[100000013]/[10000888]"
First if you want to divide the result then it will be better to change it into number and then just do the division.
Example
Number.parseInt("100000025")/Number.parseInt("100000013")
If you want to display it then better to use string interpolation
surround it with back tick
[${[0].PC}]/[${[1].PC}]
Hope this is what are you looking for

How to parse JSON to JSON in javascript?

That so crazy, but I'm trying to convert a JSON to a JSON for any reason.I have json and i checked json at http://jsonlint.com, it's ok.
{"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"ID\":\"VN00000456\",\"NAME\":\"MERRY BLUE\",\"GENDER\":\"Female\",\"BIRTHDAY\":\"03-12-1983\"},{\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"09-07-1990\"}]"}
Now, what I need convert it like this at the following
{
"columns": [
["ID"],
["NAME"],
["GENDER"],
["BIRTHDAY"]
],
"data": [
[
"VN00000123",
"JOHN GREEN",
"Male",
"15-10-1987"
],
[
"VN00000456",
"MERRY BLUE",
"Female",
"03-12-1983"
],
[
"VN00000789",
"BLACK BROWN",
"Male",
"09-07-1990"
]
]
}
Somebody've ideas for this, share with me (using javascript or jquery). Thank you so much.
This algorithm is pretty straightforward--something like the following should work:
function parse(a) {
//create object to return
var ret = {
columns: [],
data: []
};
//iterate the source array
a.forEach(function(item, i) {
if (i === 0) {
//first time through, build the columns
for (var key in item) {
ret.columns.push(key);
}
}
//now build your data item
ret.data[i] = [];
//use the column array to guarantee that the order of the fields in the source string doesn't matter
for (var j = 0; j < ret.columns.length; j++) {
var key = ret.columns[j];
ret.data[i].push(item[key]);
}
});
return ret;
}
var j = {
"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"NAME\":\"MERRY BLUE\",\"BIRTHDAY\":\"03-12-1983\",\"ID\":\"VN00000456\",\"GENDER\":\"Female\"},{\"GENDER\":\"Male\",\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"BIRTHDAY\":\"09-07-1990\"}]"
};
//j is an object with one property (d) that is a JSON string that needs parsing
var o = parse(JSON.parse(j.d));
console.log(o);
You can try this example using jQuery:
https://jsfiddle.net/de02fpha/
var dump = {"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"ID\":\"VN00000456\",\"NAME\":\"MERRY BLUE\",\"GENDER\":\"Female\",\"BIRTHDAY\":\"03-12-1983\"},{\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"09-07-1990\"}]"};
var parse = function(json) {
var columns = [];
var data = [];
$.each(json, function(index, row) {
var element = [];
for (var key in row) {
if (columns.indexOf(key) == -1) columns.push(key);
element.push(row[key]);
}
data.push(element);
});
return {columns: columns, data: data};
};
var json = $.parseJSON(dump.d);
console.log(parse(json));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
In javascript, the built in JSON class provides the two tools you need to format your JSON, no need for jquery:
JSON.parse() will handle parsing the text, and JSON.stringify can handle taking our parsed JSON and turning into a nice pretty string.
Let's slap them together.
Start with parsing and storing the JSON:
var parsedData = JSON.parse(dataToFormat);
Now to print our parsed data, we need to learn a little bit about the stringify function, specifically its space argument. Per MDN:
JSON.stringify(value[, replacer[, space]])
The space argument may be used to control spacing in the final string. If it is a number, successive levels in the stringification will each be indented by this many space characters (up to 10). If it is a string, successive levels will be indented by this string (or the first ten characters of it).
JSON.stringify({ uno: 1, dos: 2 }, null, '\t');
// returns the string:
// '{
// "uno": 1,
// "dos": 2
// }'
Note that the above code sample uses the tab character, but as described in the doc you can simply insert a number and it will use that number of spaces instead.
Alright let's print
var prettyData = JSON.stringify(parsedData, null, '\t');
prettyData should now contain a neatly formatted and indented string.
You can throw this into one line if you'd like:
var prettyData = JSON.stringify(JSON.parse(dataToFormat),null,'\t');
Now, if you wanted to add a key or something to the very top of the JSON object, you could simply define some kind of key object and attach it to the object you pass in to JSON.stringify. JSON.parse gives you a standard object, so modify it like you would any other.

How to convert a array containing object string to regular key object pair?

I am trying to convert my uri to object value, as a success level i converted and splited in to array values with colon. But i am not able to onvert those to regular object. any one suggest me a good way. I am suing underscorejs with me.
here is my code :
var ar = ["id:1231", "currency:GBP"];
var outPut = _.map(ar, function(item){
return '{' + item + '}';
})
console.log(outPut); //consoles as ["{id:1231}", "{currency:GBP}"]
how can i get result like this:
var object = {id:1231, currency:GBP}
is underscore has any in build method for this?
There are several ways you could go about this, and Underscore offers helpers for them.
One way would be to use _.reduce to incrementally add key/value pairs to an initially empty "result" object:
var obj = _.reduce(ar, function(result, item) {
var keyAndValue = item.split(":");
result[keyAndValue[0]] = keyAndValue[1];
return result;
}, {});
Note that you can do the same without Underscore unless you have to support IE 8 or earlier.
Without any third part library:
var output = {} ;
var ar = ["id:1231", "currency:GBP"];
ar.forEach(function (item) {
var values = item.split(':') ;
output[values[0]] = values[1] ;
}) ;
Output console.log(output):
Object {id: "1231", currency: "GBP"}
Here is another version using jQuery:
var newObj = {};
$.each( ar, function( i, v ) {
var kv = v.split( ":" );
newObj[ kv[0] ] = kv[ 1 ];
});
// newObj = {id:"1231", currency:"GBP"}

key-value pair undefined in javascript

For some reason I have a string like this:
"id: 123, title: something, category: science, ... "
To make a javascript object containing the key-value pairs I wrote the following method:
function stringToMap(stringToCut){
var map = {};
var listOfPairs = stringToCut.split(",");
for(var i = 0; i < listOfPairs.length; i++){
var pair = listOfPairs[i].split(":");
map[pair[0]] = pair[1];
}
return map;
}
it's important to access it with dot, not with [] brackets.
In chrome debug mode I see the expected object, but when I want to access one of it's element, like:
console.log(obj.title);
I get undefined...
What Am I doing wrong?
It's because there's a space in your key name:
console.log(obj[" title"]); // "something"
To fix this, change your first split to split on ", " instead of just ",":
var listOfPairs = stringToCut.split(", ");
JSFiddle demo.
As a further fix, you'll also want to change your second split to split on ": " rather than just ":", otherwise all your values will begin with spaces.
var pair = listOfPairs[i].split(": ");

Using an integer as a key in an associative array in JavaScript

When I create a new JavaScript array, and use an integer as a key, each element of that array up to the integer is created as undefined.
For example:
var test = new Array();
test[2300] = 'Some string';
console.log(test);
will output 2298 undefined's and one 'Some string'.
How should I get JavaScript to use 2300 as a string instead of an integer, or how should I keep it from instantiating 2299 empty indices?
Use an object, as people are saying. However, note that you can not have integer keys. JavaScript will convert the integer to a string. The following outputs 20, not undefined:
var test = {}
test[2300] = 20;
console.log(test["2300"]);
You can just use an object:
var test = {}
test[2300] = 'Some string';
As people say, JavaScript will convert a string of number to integer, so it is not possible to use directly on an associative array, but objects will work for you in similar way I think.
You can create your object:
var object = {};
And add the values as array works:
object[1] = value;
object[2] = value;
This will give you:
{
'1': value,
'2': value
}
After that you can access it like an array in other languages getting the key:
for(key in object)
{
value = object[key] ;
}
I have tested and works.
If the use case is storing data in a collection then ECMAScript 6 provides the Map type.
It's only heavier to initialize.
Here is an example:
const map = new Map();
map.set(1, "One");
map.set(2, "Two");
map.set(3, "Three");
console.log("=== With Map ===");
for (const [key, value] of map) {
console.log(`${key}: ${value} (${typeof(key)})`);
}
console.log("=== With Object ===");
const fakeMap = {
1: "One",
2: "Two",
3: "Three"
};
for (const key in fakeMap) {
console.log(`${key}: ${fakeMap[key]} (${typeof(key)})`);
}
Result:
=== With Map ===
1: One (number)
2: Two (number)
3: Three (number)
=== With Object ===
1: One (string)
2: Two (string)
3: Three (string)
Compiling other answers:
Object
var test = {};
When using a number as a new property's key, the number turns into a string:
test[2300] = 'Some string';
console.log(test['2300']);
// Output: 'Some string'
When accessing the property's value using the same number, the number is turned into a string again:
console.log(test[2300]);
// Output: 'Some string'
When getting the keys from the object, though, they aren't going to be turned back into numbers:
for (var key in test) {
console.log(typeof key);
}
// Output: 'string'
Map
ECMAScript 6 allows the use of the Map object (documentation, a comparison with Object). If your code is meant to be interpreted locally or the ECMAScript 6 compatibility table looks green enough for your purposes, consider using a Map:
var test = new Map();
test.set(2300, 'Some string');
console.log(test.get(2300));
// Output: 'Some string'
No type conversion is performed, for better and for worse:
console.log(test.get('2300'));
// Output: undefined
test.set('2300', 'Very different string');
console.log(test.get(2300));
// Output: 'Some string'
Use an object instead of an array. Arrays in JavaScript are not associative arrays. They are objects with magic associated with any properties whose names look like integers. That magic is not what you want if you're not using them as a traditional array-like structure.
var test = {};
test[2300] = 'some string';
console.log(test);
Try using an Object, not an Array:
var test = new Object(); test[2300] = 'Some string';
Get the value for an associative array property when the property name is an integer:
Starting with an associative array where the property names are integers:
var categories = [
{"1": "Category 1"},
{"2": "Category 2"},
{"3": "Category 3"},
{"4": "Category 4"}
];
Push items to the array:
categories.push({"2300": "Category 2300"});
categories.push({"2301": "Category 2301"});
Loop through the array and do something with the property value.
for (var i = 0; i < categories.length; i++) {
for (var categoryid in categories[i]) {
var category = categories[i][categoryid];
// Log progress to the console
console.log(categoryid + ": " + category);
// ... do something
}
}
Console output should look like this:
1: Category 1
2: Category 2
3: Category 3
4: Category 4
2300: Category 2300
2301: Category 2301
As you can see, you can get around the associative array limitation and have a property name be an integer.
NOTE: The associative array in my example is the JSON content you would have if you serialized a Dictionary<string, string>[] object.
Simple solution if you would rather use an array.
When adding the number just preface it with a letter.
e.g.
let ctr = 3800;
let myArray=[];
myArray["x" + ctr.toString()]="something";
myArray["x" + (ctr+1).toString()]="another thing";
Then just add the "x" in access routines that call the number as an index.
e.g.:
console.log( myArray["x3800"] );
or:
console.log( myArray["x"+ numberOfYourChoice.toString()] );
Use an object - with an integer as the key - rather than an array.
Sometimes I use a prefixes for my keys. For example:
var pre = 'foo',
key = pre + 1234
obj = {};
obj[key] = val;
Now you don't have any problem accessing them.

Categories

Resources