Related
If I have a CSV file that looks like this:
Year,Value1,Value2,Value3
2000,500,20,30
2001,40,30,20
2002,90,12,80
2003,70,55,22
...
I can read this in with D3 JS using the d3.csv("./file.csv").then(function (data)) method and I'll get data that looks like this:
[
{ Value1: "500", Value2: "20", Value3: "30", Year: "2000"},
{ Value1: "40", Value2: "30", Value3: "20", Year: "2001"},
{ Value1: "90", Value2: "12", Value3: "80", Year: "2002"},
{ Value1: "70", Value2: "55", Value3: "22", Year: "2003"}
]
This is great. It formats the data perfectly for what I need. Unfortunately for me, the incoming data I'll be working with is actually an array of arrays that will look like this:
[
["Year","Value1","Value2","Value3"],
[2000,500,20,30],
[2001,40,30,20],
[2002,90,12,80],
[2003,70,55,22]
]
Is there a built in method in D3 that will do to this array of arrays what the d3.csv() method does to CSV? As in, is there a method that will take in the array of arrays and turn it into an array of objects where each column header is associated with it's value in the given row?
So far the best solution I've come up with is to just turn the array of arrays into CSV and then parse it with D3 like this (I'm putting double quotes around each value in case of commas in values):
let csv = "";
for (const array of arrays) {
csv += '"' + array.join('","') + '"\r\n';
}
const data = d3.csvParse(csv);
This just feels a bit clunky to me, so I'm wondering if there's a quicker way to do this.
You can do this with pure JS, mapping each row to an object that you can build with reduce.
var data = [
["Year", "Value1", "Value2", "Value3"],
[2000, 500, 20, 30],
[2001, 40, 30, 20],
[2002, 90, 12, 80],
[2003, 70, 55, 22]
];
var result = data.slice(1)
.map(row => row.reduce((acc, curr, i) => {
acc[data[0][i]] = curr;
return acc;
}, {}));
console.log(result);
I have the following line of code:
$scope.listDeColaboradoresObject.forEach(item => {
item.listNmAssunto = $scope.relatorioTotalMensagensRespondidasColab
.filter(x => x.nmUsuario == item.nmUsuario)
.map(x => x.nmAssunto);
item.listNmAssunto = $scope.removeDuplicates(item.listNmAssunto);
item.listDtResposta = $scope.relatorioTotalMensagensRespondidasColab
.filter(x => x.nmUsuario == item.nmUsuario)
.map(x => x.dtResposta);
});
that runs through this array:
0: {deTipoAtendimento: "012", nmAssunto: "Cartão extraviado", nmUsuario: "15", dtResposta: "2018", total: 1}
1: {deTipoAtendimento: "012", nmAssunto: "Assunto Novo 012", nmUsuario: "Admin", dtResposta: "2018", total: 2}
2: {deTipoAtendimento: "012", nmAssunto: "Assunto Novo 012", nmUsuario: "Administrador", dtResposta: "2018", total: 1}
3: {deTipoAtendimento: "012", nmAssunto: "Assunto Novo 012", nmUsuario: "Administrador IMB", dtResposta: "2018", total: 3}
4: {deTipoAtendimento: "012", nmAssunto: "Assunto Teste GREAt", nmUsuario: "Administrador IMB", dtResposta: "2018", total: 2}
5: {deTipoAtendimento: "012", nmAssunto: "Thais 23042018", nmUsuario: "Administrador IMB", dtResposta: "2018", total: 2}
6: {deTipoAtendimento: "012", nmAssunto: "teste Alterado2", nmUsuario: "Administrador IMB", dtResposta: "2018", total: 1}
and that returns me the following array:
0: {nmUsuario: "15", listNmAssunto: Array(1), listDtResposta: Array(1), $$hashKey: "object:2975"}
1: {nmUsuario: "Admin", listNmAssunto: Array(1), listDtResposta: Array(1), $$hashKey: "object:2976"}
2: {nmUsuario: "Administrador", listNmAssunto: Array(1), listDtResposta: Array(1), $$hashKey: "object:2977"}
3: {nmUsuario: "Administrador IMB", listNmAssunto: Array(4), listDtResposta: Array(4), $$hashKey: "object:2978"}
My question is how do I at the time of the map insert both the nmSubject and the dtResponse within the same array
Why you don’t map into one object?
Like this:
$scope.listDeColaboradoresObject.forEach(item => {
item.listAssunto = $scope.relatorioTotalMensagensRespondidasColab
.filter(x => x.nmUsuario == item.nmUsuario)
.map(x => {a:x.nmAssunto,b: x.dtResposta});
item.listNmAssunto = $scope.removeDuplicates(item.listAssunto);
});
The code you've will just update the existing array. I'm not sure how it creates the output you've posted. But, looking at your output, I'm assuming you want to group based on the nmUsuario and create an array of objects with 2 array properties. You can do the following using reduce, destructiring and Object.values
const input = [{deTipoAtendimento:"012",nmAssunto:"Cartão extraviado",nmUsuario:"15",dtResposta:"2018",total:1},{deTipoAtendimento:"012",nmAssunto:"Assunto Novo 012",nmUsuario:"Admin",dtResposta:"2018",total:2},{deTipoAtendimento:"012",nmAssunto:"Assunto Novo 012",nmUsuario:"Administrador",dtResposta:"2018",total:1},{deTipoAtendimento:"012",nmAssunto:"Assunto Novo 012",nmUsuario:"Administrador IMB",dtResposta:"2018",total:3},{deTipoAtendimento:"012",nmAssunto:"Assunto Teste GREAt",nmUsuario:"Administrador IMB",dtResposta:"2018",total:2},{deTipoAtendimento:"012",nmAssunto:"Thais 23042018",nmUsuario:"Administrador IMB",dtResposta:"2018",total:2},{deTipoAtendimento:"012",nmAssunto:"teste Alterado2",nmUsuario:"Administrador IMB",dtResposta:"2018",total:1}]
const merged = input.reduce((r,{ nmUsuario, nmAssunto, dtResposta }) => {
r[nmUsuario] = r[nmUsuario] || {nmUsuario, listNmAssunto: [], listDtResposta:[]};
r[nmUsuario].listNmAssunto.push(nmAssunto);
r[nmUsuario].listDtResposta.push(dtResposta);
return r;
},{})
const output = Object.values(merged);
console.log(output)
As per your results comment, it looks like you want to group your list by nmUsuario, but create a single array of objects that hold the relevant nmAssunto and dtResposta. You can achieve this with reduce(). Basically, you create an object with an empty array for each nmAssunto, and push a new object into the correct array each iteration. Then use Object.values() to convert to the final output array.
const data = [
{deTipoAtendimento:"012",nmAssunto:"Cartão extraviado",nmUsuario:"15",dtResposta:"2018",total:1},
{deTipoAtendimento:"012",nmAssunto:"Assunto Novo 012",nmUsuario:"Admin",dtResposta:"2018",total:2},
{deTipoAtendimento:"012",nmAssunto:"Assunto Novo 012",nmUsuario:"Administrador",dtResposta:"2018",total:1},{deTipoAtendimento:"012",nmAssunto:"Assunto Novo 012",nmUsuario:"Administrador IMB",dtResposta:"2018",total:3},
{deTipoAtendimento:"012",nmAssunto:"Assunto Teste GREAt",nmUsuario:"Administrador IMB",dtResposta:"2018",total:2},
{deTipoAtendimento:"012",nmAssunto:"Thais 23042018",nmUsuario:"Administrador IMB",dtResposta:"2018",total:2},
{deTipoAtendimento:"012",nmAssunto:"teste Alterado2",nmUsuario:"Administrador IMB",dtResposta:"2018",total:1}
]
const groups = data.reduce((r, { nmUsuario, nmAssunto, dtResposta }) => {
r[nmUsuario] = r[nmUsuario] || {
nmUsuario,
listAssunto: []
}
r[nmUsuario].listAssunto.push({
a: nmAssunto,
b: dtResposta
})
return r
}, {})
console.log(Object.values(groups))
I have two array like this:
var actval = [
0: "3"
1: "22-Nov-2018 15:32:36 IST"
2: "22-Nov-2018 15:32:40 IST"
3: "3"
4: "22-Nov-2018 15:32:36 IST"
5: "22-Nov-2018 15:32:40 IST"
6: "3"
7: "22-Nov-2018 15:32:36 IST"
8: "22-Nov-2018 15:32:40 IST"
]
var id = [
0: "STATUS"
1: "STARTTIME"
2: "ENDTIME"
3: "STATUS"
4: "STARTTIME"
5: "ENDTIME"
6: "STATUS"
7: "STARTTIME"
8: "ENDTIME"
]
What I want to do is make a final array which would have keys as STATUS, STARTTIME, ENDTIME and each of the keys can have multiple values like this:
finalarray = [
STATUS: ["3", "3", "3"]
STARTTIME: ["22-Nov-2018 15:32:36 IST", "22-Nov-2018 15:32:36 IST", "22-Nov-2018 15:32:36 IST"]
ENDTIME: ["22-Nov-2018 15:32:40 IST", "22-Nov-2018 15:32:40 IST", "22-Nov-2018 15:32:40 IST"]
]
For this I have tried this approach :
for (i = 0; i < id.length; i++) {
currentKey = id[i];
currentVal = actval[i];
result[currentKey] = currentVal;
}
but it only gives me one value for each key not every value:
How can i get the each value in that array linked to that key?
Solved Just adding one check in your code
try this:
var result = [];
for (i = 0; i < id.length; i++) {
let currentKey = id[i];
let currentVal = actval[i];
if(result[currentKey])
result[currentKey] = [...result[currentKey],currentVal];
else
result[currentKey] = [currentVal];
}
If actval always look like that and you want to extract the top 3 values you could just do a shift() something like this.
var final = {STATUS: [], STARTTIME:[], ENDTIME:[]};
for (let i=0; actval.length > i; i++) {
final.STATUS.push( actval.shift() );
final.STARTTIME.push( actval.shift() );
final.ENDTIME.push( actval.shift() );
}
What you are doing is just writing over the same array value with =.
You are always doing result['key'] = 'value';
Try this assuming actval is array not object:
finalobject = {
STATUS: actval.filter(e=>e.length===1),
STARTTIME: actval.filter((e, i)=>i%3).filter((e, i)=>i%2===0),
ENDTIME: actval.filter((e, i)=>i%3).filter((e, i)=>i%2!==0),
};
I will update question, when you will clarify some things and change this "arrays" to objects.
This is working for list:
> Array.prototype.slice.call([1,2,3])
> [1, 2, 3]
How to create list from this type of data {1: "1", 2: "2", 3: "3"} ? Are there other methods than iterating object with for ?
the Array.prototype.slice.call() is not working here and gives []
This came from data = Object {0: Object, 1: Object, 2: Object, total : '29'} and then i delete data['total'] and need to access to slice, pop and other methods of Array
You could use the keys and map the values.
var o = {1: "1", 2: "2", 3: "3"},
a = Object.keys(o).map(function (k) {
return o[k];
});
console.log(a);
console.log(Array.prototype.slice.call({1: "1", 2: "2", 3: "3", length:5}));
The question arised, why Array.prototype.slice.call does not work. Basically because a length property is missing.
Only properties, which can be used as indices are used.
var o1 = {1: "1", 2: "2", 3: "3"},
o2 = {1: "1", 2: "2", 3: "3", length: 5},
o3 = {1: "1", 2: "2", 3: "3", abc: 42, length: 5},
o4 = {0: "0", 1: "1", 2: "2", 3: "3"};
o4.length=Object.keys(o4).length;
console.log(Array.prototype.slice.call(o1));
console.log(Array.prototype.slice.call(o2));
console.log(Array.prototype.slice.call(o3));
console.log(Array.prototype.slice.call(o4));
Note: Dynamic length of properties-in-object could be assigned using Object.keys(OBJECT). The cause of getting undefined in console is missing property at index 0
var list = [];
for (item in obj) {
list.push(obj[item]);
}
//use list.push(parseInt(obj[item])) for number array
You can also do the following if you want it straight
Object.values(obj);
I don't know if the title is the right one for what I want to do.
I have the following array of objects
array([0]: {category: "10",
question: "101"},
[1]: {category: "10",
question: "102"},
[2]: {category: "20",
question: "201"}
);
And I want to group all the elements into something like this:
array([0]: {category: "10", {question: "101",
question: "102"}},
category: "20", {question: "201"}});
I don't know if this is possible or if there's another better way to solve this problem (maybe with a two-dimensional array?) but any help would be very appreciated.
Thanks!
Sorry for the lack of information, here is how I create my array of objects:
var arr_sections = [];
var arr_questions = [];
var jsonObj = [];
$('.ui-sortable-nostyle').each(function(){
arr_sections.push($(this).attr("sec_id"));
});
// create json object with pairs category - question
$(".sortable2").each(function(i){
$(this).children().each(function(j){
var cat = arr_sections[i];
jsonObj.push({
category: arr_sections[i],
question: $(this).attr("ques_id")
});
});
});
And got an array of objects with the following structure:
[Object, Object, Object, Object, Object]
0: Object
category: "1052"
question: "3701"
__proto__: Object
1: Object
category: "1053"
question: "3702"
__proto__: Object
2: Object
category: "483"
question: "1550"
__proto__: Object
3: Object
category: "483"
question: "1548"
__proto__: Object
4: Object
category: "483"
question: "1549"
__proto__: Object
length: 5
Tried to create my new array:
for(var i = 0; i < jsonObj.length; i++){
temp[jsonObj[i].category] = jsonObj[i].question;
}
But I don't get all values:
[483: "1549", 1052: "3701", 1053: "3702"]
You have:
var arr = [
{category: "10", question: "101"},
{category: "10", question: "102"},
{category: "20", question: "201"}
];
You want (i suppose):
var arrRequired = [
{category: "10", question : ["101", "102"] },
{category: "20", question : ["201"] }
];
I will give you:
var obj = {
"10" : ["101", "102"],
"20" : ["201"]
};
To convert what you have to what i will give you, you can do:
var result = {};
arr.forEach(function(item) {
if (!result[item.category])
result[item.category] = [item.question];
else
result[item.category].push(item.question);
});
To get to what you want from what i gave you, you can do:
var arrRequired = [];
for (var category in result){
arrRequired.push({ 'category' : category, 'question' : result[category] });
}
If that is not what you want, then perhaps you should explain it better, using valid syntax.
Here is the answer to what you asked:
var object1 = JSON.parse(jsonString1);
// Do something to object1 here.
var jsonString2 = JSON.stringify(object1);