Dynamic Key Value Array with Multiple Values in Javascript - javascript

I have:
var data = [];
I want to dynamically create string array like this:
for(var i=0; i < files.length; i++){
data[i].part1 = "abc";
data[i].part2 = "def";
data[i].part3 = "ghi";
}
Is this possible? I tried it and it complained 'Cannot set property 'part1' of undefined'
Then I want to sort the data array by part1 values so:
data[0] = {3,a,b};
data[1] = {1,a,b};
data[2] = {5,a,b};
becomes:
data[0] = {1,a,b,c};
data[1] = {3,a,b,c};
data[2] = {5,a,b,c};
The reason I want to do this is because after the sort is done, i need to change the
data[i].part2
to something else after sorting!

You could do this:
for (var i = 0; i < files.length; i++) {
data[i] = {};
data[i].part1 = "abc";
data[i].part2 = "def";
data[i].part3 = "ghi";
}
to set data[i] to an empty object, then fill it piece by piece. Or
for (var i = 0; i < files.length; i++) {
data[i] = {
part1: "abc",
part2: "def",
part3: "ghi"
};
}
to set data[i] to the complete object all at once.
I don't understand the data[0] = {3,a,b}; part, though: {3,a,b} is a syntax error and it doesn't resemble your other code (which doesn't mention 3 or a or b).
But you can easily sort an array of objects by a particular property:
data.sort(function (a, b) {
return (a.part1 > b.part1) - (a.part1 < b.part1);
});
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort for details.

Related

How to parse a string into no type

I am parsing a csv file:
let lines = csvData.split(/\r\n|\n/);
let headers = lines[0].split(',');
for (let i = 1; i < lines.length; i++) {
let values = lines[i].split(',');
let item = {};
for (let j = 0; j < headers.length; j++) {
item[headers[j]] = values[j];
}
items.push(item);
}
return items;
I am getting its data. However, the data are all strings. I want to pass them into JSON, and make them have no type, so I can pass them into variables with different types. I don't want to use parseInt/parseFloat directly, because I don't know the specific type of each variable.
However, each time I pass the values to JSON, they are all strings, e.x. "1234", not 1234. Normally I can pass JSON data to class without no type, but this time I convert the csvData into JSON, the JSON data are all strings. I guess it is because the split function makes it a string?
Optional:
I can pass the type into this function, like readCsvFile<T>(csvData), can I do something like:
if (typeof(T[headers[j]]) == 'number') {
item[headers[j]] = parseFloat(values[j]);
} else {
item[headers[j]] = values[j];
}
But T[header[j]] doesn't pass the compilation.
I would do something more functional.
//Define variables
var csvData = "field1a,field2a,field3a\r\nfield1b,field2b,field3b";
var linesAsObjects = [];
var lines = csvData.split(/\r\n|\n/);
//Split fields here
var splitFields = function(line){
let fields = line.split(',');
addItem(fields);
}
// Assign field values to object or formatting here
var addItem = function(fields){
let obj = {};
obj.field1 = fields[0];
obj.field2 = fields[1];
obj.field3 = fields[2];
linesAsObjects.push(obj);
}
// Call the code for each line
lines.forEach(splitFields);
//Printing lines and fields as assigned to an object.
console.log(linesAsObjects);
If you don't need to know the type (and you actually not trying to get the value of the property with the unknown type), then you can use the "unknown" type https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html
This is far better than "any" and you can type the data at the point you need to get it.
Try to use type any for the attributes.
// add the fields you have from the CSV
class ResultFromCSV {
myValue: any;
otherValue: any;
}
...
let lines = csvData.split(/\r\n|\n/);
let headers = lines[0].split(',');
for (let i = 1; i < lines.length; i++) {
let values = lines[i].split(',');
// instantiate here
let item = new ResultFromCSV();
for (let j = 0; j < headers.length; j++) {
item[headers[j]] = values[j];
}
items.push(item);
}
return items;

Checking to see if key-value has the same value

So I'm turning a .csv file into an array of key-value pairs, I'm trying to print each unique value and i'm trying to figure out how I can check to make sure the values aren't identical. So for example:
var data = $.csv.toObjects(csv);
will turn everything into
[
{heading1:"value1_1",heading2:"value2_1",heading3:"value3_1",heading4:"value4_1",heading5:"value5_1"}
{heading1:"value1_2",heading2:"value2_2",heading3:"value3_2",heading4:"value4_2",heading5:"value5_2" }
]
I want to check if heading1 has the same value in both instances and if it does to only print the first instance of that value.
Convert your data into key–value pairs, where keys are the values from "heading1" like so:
var data = [
{heading1:"value1_1",heading2:"value2_1",heading3:"value3_1",heading4:"value4_1",heading5:"value5_1"},
{heading1:"value1_2",heading2:"value2_2",heading3:"value3_2",heading4:"value4_2",heading5:"value5_2" },
];
var filtered = {};
for (var i = 0, max = data.length; i < max; i++) {
var record = data[i];
if (!filtered[record.heading1]) {
filtered[record.heading1] = {};
}
filtered[record.heading1] = record;
}
var keys = Object.keys(filtered);
for (var i = 0, max = keys.length; i < max; i++) {
console.log(filtered[keys[i]]); // do print
}

How do I order items returned in JSON format?

I want to sort the following information by the string value (not the key number). I am able to convert it to a dictionary and order by value ("AAA" and "CCC") in the code below... now the only question is, how do I convert the dictionary to the same format below in the parseJSON function? I cannot change the format of the JSON so that's out of the question. Any other ways are appreciated. I cannot move it to an array or anything. As stated in my question, the JSON format exists as is and I cannot change it.
var studentCollection.Groups = $.parseJSON("{\"1000\":\"CCC\", \"1001\":\"AAA\"}");
//Sorting the studentCollection.Groups dictionary.
//Even though the groups come back as valid/sorted JSON
//upon parsing the JSON, the groups sorting gets lost
var items = Object.keys(studentCollection.Groups).map(function (key) {
return [key, studentCollection.Groups[key]];
});
items.sort(function (first, second) {
if (first[1] < second[1])
return -1;
if (first[1] > second[1])
return 1;
return 0;
});
you can just convert your object values to array which you will sort and then again assign step-by-step to an object:
var j = "{\"1000\":\"AAA\", \"1001\":\"ZZZ\"}";
var o = JSON.parse(j);
var keys = Object.keys(o);
var values = [];
for(var i = 0; i < keys.length; i++) values.push(o[keys[i]]);
values.sort();
for(var i = 0; i < values.length; i++) o[keys[i]] = values[i];
alert( JSON.stringify(o) );
UPDATE
since example above has not keep the keys base order this one should:
var j = "{\"1000\":\"AAA\", \"1002\":\"ZZZ\", \"1004\":\"DDD\", \"1003\":\"BBB\", \"1001\":\"YYY\"}";
j = j.replace(/\"\d+\"\:/g, function myFunction(x){ return x.substring(0,1) + "_" + x.substring(1) })
var o = JSON.parse(j);
var keys = Object.keys(o);
var values = [];
for(var i = 0; i < keys.length; i++) values.push(o[keys[i]]);
values.sort();
for(var i = 0; i < values.length; i++) o[keys[i]] = values[i];
var j = JSON.stringify(o)
j = j.replace(/\"\_\d+\"\:/g, function myFunction(x){ return x.substring(0,1) + x.substring(2) })
alert( j );
try it here: https://jsfiddle.net/pyqw8hvt/1/
the idea is to add _ before every integer key to make it non-integer and in this way avoid automatic sorting inside parsed object, and then after stringifying the object erase the added _ inside keys
I don't know if this is the best way to do it, you'd have to call JSON.stringify twice, but it gives the output you're looking for:
var studentCollection = {};
studentCollection.Groups = $.parseJSON("{\"1000\":\"CCC\", \"1001\":\"AAA\"}");
var items = Object.keys(studentCollection.Groups).map(function (key) {
return [key, studentCollection.Groups[key]];
});
items.sort(function (first, second) {
if (first[1] < second[1])
return -1;
if (first[1] > second[1])
return 1;
return 0;
});
result = JSON.stringify(JSON.stringify(toObject(items)))
console.log(result);
// outputs: "{\"1001\":\"AAA\",\"1000\":\"CCC\"}"
// checking if ordering remains
console.log($.parseJSON(result));
// outputs: {"1001":"AAA","1000":"CCC"}
function toObject(arr) {
return arr.reduce(function(o, v, i) {
o[v[0]] = v[1];
return o;
}, {});
}

JavaScript for loop closure issue

I am adding all categories after ticking them to true if they exists in selected categories of result but it combines previous categories results with current one. I tried closure but it doesn't give me fresh object. Check out fiddle.
var allCatsResult = [{"id":1},{"id":2}, {"id":3}, ... ];
var catsArray = [1, 2] // Array of ids from allCatsResult
var result = [
{"id":1, selectedCategories:[{"id":1},{"id":2}]},
{"id":2, selectedCategories:[{"id":4},{"id":5}]},
...
];
for (var i = 0; i < results.length; i++) {
var tmp = allCatsResult; // tried to add function form here didn't work
for (var k = 0; k < results[i].selectedCategories.length; k++) {
var index = catsArray.indexOf(results[i].selectedCategories[k].category_id);
if(index !== -1) {
tmp[index].ticked = true;
}
}
results[i].categories = tmp;
}
Above code gives combined result for ticked = true for all categories in each result.
You need to copy/clone the array of objects, or you're manipulating the original. There are a few ways apparently. I chose the following:
var tmp = JSON.parse(JSON.stringify(allCatsResult));
This will create a new array of objects in tmp, and it will correctly only modify the clone.

Javascript arrays storing values

There might be a very simple solution my problem but just not being able to find one so please help me to get to my solution in the simplest way...
The issue here is that I have data being displayed in a tabular form. Each row has 5 columns and in one of the columns it shows multiple values and so that's why I need to refer to a value by something like this row[1]['value1'], row[1]['value2'] & then row[2]['value1'], row[2]['value2'].
I declare the array
var parray = [[],[]];
I want to store the values in a loop something like this
for(counter = 0; counter < 10; counter ++){
parray[counter]['id'] += 1;
parray[counter]['isavailable'] += 0;
}
Later I want to loop through this and get the results:
for (var idx = 0; idx < parray.length; idx++) {
var pt = {};
pt.id = parray[schctr][idx].id;
pt.isavailable = parray[schctr][idx].isavailable;
}
Obviously iit's not working because Counter is a numeric key and 'id' is a string key ..my question how do I achieve this ??
Thanks for all the answers in advance.
JS has no concept of "associative arrays". You have arrays and objects (map). Arrays are objects though, and you can put keys, but it's not advisable.
You can start off with a blank array
var parray = [];
And "push" objects into it
for(counter = 0; counter < 10; counter++){
parray.push({
id : 1,
isAvailable : 0
});
}
Then you can read from them
for (var idx = 0; idx < parray.length; idx++) {
// Store the current item in a variable
var pt = parray[idx];
console.log(pt);
// read just the id
console.log(parray[idx].id);
}
Like I did here
What you want inside your array is just a plain object:
// just a regular array
var parray = [];
for(var counter = 0; counter < 10; counter++){
// create an object to store the values
var obj = {};
obj.id = counter;
obj.isavailable = 0;
// add the object to the array
parray.push(obj);
}
later:
for (var idx = 0; idx < parray.length; idx++) {
var pt = parray[idx];
// do something with pt
}

Categories

Resources