I want to iterate over a JSON in javasacript and create something like this as output
{
"seriesData": [
{
"name": "John",
"data": [
5,
3,
4
]
},
{
"name": "Jane",
"data": [
2,
2,
3
]
},
{
"name": "Joe",
"data": [
3,
4,
4
]
}
]
}
So, I essentially need to add values in data array for each key inside my for loop.
Input looks like:
{"Records":[{"name":"Jan'10","users":[{"name":"John","y":5},{"name":"Jane","y":2},{"name":"Joe","y":3}]},{"name":"Jan'10","users":[{"name":"John","y":3},{"name":"Jane","y":2},{"name":"Joe","y":4}]},{"name":"Jan'10","users":[{"name":"John","y":4},{"name":"Jane","y":3},{"name":"Joe","y":4}]}]};
Can someone please suggest how can this be achieved.
you could try something like this:
var dataList = {};
function addData(name){
if( dataList[name] == undefined)
dataList[name] = [];
for (var i = 1; i < arguments.length; i++) {
dataList[name].push(arguments[i]);
}
}
function packData(){
var pack = []
for(var e in dataList){
pack.push({
name: e,
data:dataList[e].sort(function(a,b){return a-b})
});
}
return pack;
}
addData("Joe", 1);
addData("Jan", 2, 10);
addData("Joe", 3, 5, 10, 18, 500);
addData("Jan", 4);
addData("Joe", 5);
addData("Jan", 6);
console.log( packData() );
use addData(name, data); to append data to a name and afterwards pack this data with packData()
EDIT:
Sry switched to PHP for a while... fixed the script XD
Related
I have an array that I'm retrieving from an API. The array looks like this:
[{
"name": "Rachel",
"count": 4,
"fon": "46-104104",
"id": 2
},
{
"name": "Lindsay",
"count": 2,
"fon": "43-053201",
"id": 3
},
{
"name": "Michael",
"count": 5,
"fon": "46-231223",
"id": 4
}]
Then I loop through the array to create an array containing only the names.
function buildName(data) {
for (var i = 0; i < data.length; i++) {
nameList.push(data[i].name)
}
}
This also works so far, but I would like to create an array in which each name occurs as often as the object count says.
For example, the name Michael should appear five times in the array and Lindsay twice.
[
"Rachel",
"Rachel",
"Rachel",
"Rachel",
"Lindsay",
"Lindsay",
"Michael",
"Michael",
"Michael",
"Michael"
"Michael"
]
For each object create a new array using count, and then fill it with the name.
If you use flatMap to iterate over the array of objects. It will return a new array of nested objects but then flatten them into a non-nested structure.
const data=[{name:"Rachel",count:4,fon:"46-104104",id:2},{name:"Lindsay",count:2,fon:"43-053201",id:3},{name:"Michael",count:5,fon:"46-231223",id:4}];
const out = data.flatMap(obj => {
return new Array(obj.count).fill(obj.name)
});
console.log(out);
I've upgraded your functions but you can use the map method
function buildName(data){
for (let i = 0; i < data.length; i++){
let numToLoop = data[i].count
let name = data[i].name
for (let z = 0; z < +numToLoop; z++){
nameList.push(name)
}
}
}
Use an inner while loop inside the for loop:
const data = [{
"name": "Rachel",
"count": 4,
"fon": "46-104104",
"id": 2
},
{
"name": "Lindsay",
"count": 2,
"fon": "43-053201",
"id": 3
},
{
"name": "Michael",
"count": 5,
"fon": "46-231223",
"id": 4
}]
function buildName(data){
const result = [];
for (let i = 0; i < data.length; i += 1) {
let item = data[i];
let count = item.count;
while (count > 0) {
result.push(item.name);
count -= 1;
}
}
return result;
}
console.log(buildName(data));
Just add an inner loop with as many iterations as the "count" property in the object:
function buildName(data) {
const nameList = [];
for (var i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].count; j++) {
nameList.push(data[i].name);
}
}
return nameList;
}
For fun
import { pipe } from 'fp-ts/lib/function';
import { chain, replicate } from 'fp-ts/lib/Array';
const arr = ...
const result = pipe(
arr,
chain(i => replicate(i.count, i.name))
);
You can use .flapMap() for that:
const arr = [{ "name": "Rachel", "count": 4, "fon": "46-104104", "id": 2 }, { "name": "Lindsay", "count": 2, "fon": "43-053201", "id": 3 }, { "name": "Michael", "count": 5, "fon": "46-231223", "id": 4 }];
const result = arr.flatMap(({count, name}) => Array(count).fill(name));
console.log(result);
Effectively you turn every element into an array of the the name property repeated count times which is then flattened into a single array.
It can be done via creating an array with repeated names in this way:
Array(count).fill(name)
Then you have to spread it into resulting array.
You can try this one-liner
const getNames = (data) =>
data.reduce(
(names, { name, count }) => [...names, ...Array(count).fill(name)],
[]
)
Note that a pure function is presented here, which is generally the preferred way of writing code. However, updating your example code might look like this
const getNames = (data) =>
data.reduce(
(names, { name, count }) => [...names, ...Array(count).fill(name)],
[]
)
function buildName(data) {
nameList = getNames(data)
}
I need to modify a data which is coming from API. The data is coming in the form of array of objects.
const crosses = [
{
fatherLineId: 8,
fatherLineName: "2ART18-0008",
id: 54,
motherLineId: 5,
motherLineName: "2ART18-0005",
},
{
fatherLineId: 3
fatherLineName: "2ART18-0003",
id: 55,
motherLineId: 5,
motherLineName: "2ART18-0005",
}
]
I want my data to be restructured in the form of:
const resultantArr = [
{
enteryNumber: 1,
ParentName: "2ART18-0008"
},
{
entryNumber: 2,
ParentName: "2ART18-0005",
},
{
entryNumber: 3,
ParentName: "2ART18-0003"
},
and so on ...
];
Here the parentName property will have motherLineName values and fatherLineName values in the order.
When you get the result of the api call, loop through it and map the data toy our custom object, I can't provide a complete example based on your question but something like this:
You may also need to parse the apiresult into json using JSON.parse()
var resultantArr = [];
for(var i = 0; i < apiresult.length; i++)
{
resultantArr.push({"enteryNumber" : i + 1 , "ParentName" : apiresult[i].fatherLineName });
}
Loop over the array and push two separate objects into an output array. And keep a record of each object entryname that you increment by two at the end of each iteration.
const crosses=[{fatherLineId:8,fatherLineName:"2ART18-0008",id:54,motherLineId:5,motherLineName:"2ART18-0005"},{fatherLineId:3,fatherLineName:"2ART18-0003",id:55,motherLineId:5,motherLineName:"2ART18-0005"}];
const out = [];
let count = 1;
crosses.forEach(obj => {
const { fatherLineName, motherLineName } = obj;
out.push({
entryNumber: count,
parentName: fatherLineName
});
out.push({
entryNumber: count + 1,
parentName: motherLineName
});
count = count + 2;
});
console.log(out);
Hope it helps you... 🙂
const crosses = [
{
fatherLineId: 8,
fatherLineName: "2ART18-0008",
id: 54,
motherLineId: 5,
motherLineName: "2ART18-0005",
},
{
fatherLineId: 3,
fatherLineName: "2ART18-0003",
id: 55,
motherLineId: 5,
motherLineName: "2ART18-0005",
}
];
var result = [];
var count = 1;
crosses.forEach(cross => {
result.push({
parentName: cross.fatherLineName,
entryNumber: count++,
}),
result.push({ parentName: cross.motherLineName,
entryNumber: count++,
})
});
result
I have an array "source"
source : [
{
"id": 1,
"secondId": 1
},
{
"id": 2,
"secondId": 1
},
{
"id": 3,
"secondId": 1
}
]
I want to rename the secondId when there are duplicate like this:
[
{
"id": 1,
"secondId": 1
},
{
"id": 2,
"secondId": 1_2
},
{
"id": 3,
"secondId": 1_3
}
]
I have this so far:
for (i = 0 ; i < source.length ; i++) {
for (j = 0 ; j < source.length ; j++){
if (source[i]["id"] != source[j]["id"] && source[i]["secondId"] === source[j]["secondId"]){
source[j]["secondId"] += "_" + (i+1);
}
console.log(source[j]["secondId"]);
}
}
and I'm getting:
[
{
"id": 1,
"secondId": 1
},
{
"id": 2,
"secondId": 1_2
},
{
"id": 3,
"secondId": 1_2_3
}
]
I tried to use some:
if(source[j]["secondId"].includes("_"+ (i+1))){
console.log(source[j]["secondId"].split("_"+ (i+1)).shift());
}
but I'm getting:
"secondId": 1
"secondId": 1
"secondId": 1_2
How can I do it? Any tips please?
A version using Array.reduce:
let source = [
{
"id": 1,
"secondId": 1
},
{
"id": 2,
"secondId": 1
},
{
"id": 3,
"secondId": 1
}];
let output = Object.values(
source.reduce((a, e, i) => {
let testId = e.secondId.toString();
if (a[testId]) {
testId = testId.split("_")[0] + "_" + (i + 1);
}
a[testId] = {...e, secondId: testId};
return a;
}, {})
);
console.log(output);
This may be a solution to achieve the (assumed) desired objective:
Code Snippet
const markDupes = arr => (
arr.reduce(
(fin, {id, secondId}) => ({
tm: {
[secondId]: (fin.tm[secondId] || 0) + 1
},
newArr: [
...fin.newArr,
{id, secondId: secondId.toString() + (
fin.tm[secondId] > 0 ? `_${fin.tm[secondId]+1}` : ''
)}
]
}),
{ tm: {}, newArr: [] }
)?.newArr
);
const source = [{
"id": 1,
"secondId": 1
},
{
"id": 2,
"secondId": 1
},
{
"id": 3,
"secondId": 1
}
];
console.log(markDupes(source));
Explanation
Use .reduce to iterate over the array of objects
Set up an initial fin object with two props tm (tracking-map) and newArr (the result-array which will have the secondId updated as desired)
For each object, destructure to directly access id and secondId
Update the map tm based on the secondId with a counter
Append to the newArr an object with id and secondId props with the latter (secondId) being converted to a string to store values of the format 1_2, 1_3, etc
NOTE: This may not be an optimal solution.
When you convert 1 to 1_2 or 1_3 it is converting a number to a string which will be a huge pain when you have a use for the number later. Instead what i have done is convert that number to a decimal for as 1.2 ,1.3 which means you can do all sorts of computation on a number without much conversion
let source = [
{
"id": 1,
"secondId": 1
},
{
"id": 2,
"secondId": 1
},
{
"id": 3,
"secondId": 1
}
];
let val = {};
for (const i in source) {
let v = source[i].secondId
val[v] = val[v] ? val[v] : v
if (val[v] !== 1) {
console.log(source[i].id, v);
source[i].secondId = Number(v.toFixed(2)) + (val[v] * 0.1)
}
val[v]++
}
console.log(source);
if you are really kean of using string instead use source[i].secondId = v+'_'+val[v] instead inside the if by changing the original source json object as well
I have two javascript array
let a=[{id:1},{id:2},{id:3}];
let b=[{count:35, name:'test', age:12}, {count:45 name:'test2', age:9}];
and two array push into i need final Array format is
[{count:35,name:'test', age,12, id:1} , {count:35, name:'test', age:12,id:2},{count:35, name:'test', age:12,id:3},{count:45,name:'test', age,9, id:1} , {count:45, name:'test', age:9,id:2},{count:45, name:'test', age:9,id:3} ]
And i trying
for ( var index=0; index<b.length; index++ ) {
for ( var j=0; j<a.length; j++ ) {
for (const [key, value] of Object.entries(a[j])) {
//if(j==index)
b[index][key]=value;
k[j]=b[index];
}
console.log( b[index]);
c.push(b[index]);
}
}
console.log(c);
and it shows final value is
please any body help to fix the problem
Your current implementation, is essentially updating the same b objects over and over, x number of times, changing their IDs each time through, ending at 3.
You need to "clone" the objects, so they are separate objects, like so:
let p = []; // Permutations
let a = [{id:1},{id:2}]; // Renditions...
// Presets...
let b = [{count:35, name:'test', age:12}, {count:45, name:'test2', age:9}];
// for each Rendition
a.forEach(function(a) {
// for each Preset
b.forEach(function(b){
// generate Permutation and Clone, object of b with additional id prop
p.push(Object.assign({id: a.id}, b)); // <-- Cloned here...
});
});
console.log(p)
for the sake of clarity, you might consider changing the id prop to grouping or group or group_id.
You could use flatMap:
let a=[{id:1},{id:2},{id:3}];
let b=[{count:35, name:'test', age:12}, {count:45, name:'test2', age:9}];
let m = b.flatMap(itemB => a.map(itemA => ({...itemB, ...itemA })))
console.log(m);
I got your problem. The thing is that you are mutating the same b object every iteration, that's why in the end you get id = 3 for every element. You can use a deep copy of b in each cycle, and the error should be gone.
Here's one way to deep clone, not the most efficient but it is very clear:
const bCopy = JSON.parse(JSON.stringify(b[index]));
for (const [key, value] of Object.entries(a[j])) {
//if(j==index)
bCopy[key]=value;
k[j]=bCopy; // what's this for?
}
console.log(bCopy);
c.push(bCopy);
Reduce b and for each item b1, reduce a. When reducing a, just assign both b1 and a1 to a new object.
const expectedValue = JSON.stringify(JSON.parse(
document.getElementById('expected').value))
let a = [
{ id: 1 },
{ id: 2 },
{ id: 3 }
]
let b = [
{ count: 35, name: 'test', age: 12 },
{ count: 45, name: 'test2', age: 9 }
]
let c = b.reduce((res, b1) =>
a.reduce((res1, a1) =>
[...res1, Object.assign({}, b1, a1)], res), [])
console.log(JSON.stringify(c) === expectedValue)
.as-console-wrapper { top: 0; max-height: 100% !important; }
#expected { display: none; }
<textarea id="expected">
[
{ "count": 35, "name": "test", "age": 12, "id": 1 },
{ "count": 35, "name": "test", "age": 12, "id": 2 },
{ "count": 35, "name": "test", "age": 12, "id": 3 },
{ "count": 45, "name": "test2", "age": 9, "id": 1 },
{ "count": 45, "name": "test2", "age": 9, "id": 2 },
{ "count": 45, "name": "test2", "age": 9, "id": 3 }
]
</textarea>
Try this changes.
let a=[{id:1},{id:2},{id:3}];
let b=[{count:35, name:'test', age:12}, {count:45, name:'test2', age:9}];
let c=[];
for ( var index=0; index<b.length; index++ ) {
for ( var j=0; j<a.length; j++ ) {
var obj=b[index];
for (const [key, value] of Object.entries(a[j])) {
obj[key]=value;
}
c.push(obj);
}
}
console.log(c);
I am writing code for the drawing chart for support time series data by using VizGrammar JS library.
I am facing an issue with objects and arrays in javascript.
I am getting lots of Arrays,from that I need only first block of arrays only. How can I access that?
var data = [
{
...
},
"data": [
["test", 3.12 , Hello],
.....
],
}
];
innerDataValues = data[0].data;
console.log(innerDataValues);
$scope.getData = function(data) {
var innerData = '';
for (var i = 0 ; i < data.length; i++) {
for (var j = 0; j<data[i].data.length; j++) {
innerData += data[i].steps[j];
}
}
return innerData;
}
Here data am getting inside the argument is your Whole data , and the loop with var j is for your innerData . If you want to get particular data inside the innerData means you can put
innerData += data[i].steps[j].Whatever You want;
(Instead of $scope you can use 'this' also) Hope it will works .
You can obtain first block of each element by using array.map:
ES6 version
var innerDataValues = data.map(element => element.data);
ES5 version
var innerDataValues = date.map(function(el){ return el.data; })
Edit : that works with this exemple :
var data = [{
"prop" : {
"val" : 12,
"eval": 36
},
"data": [
["test", 3.12 ,"Hello"],
["toto", 18, "titi"]
]
},
{
"prop" : {
"val" : 25,
"eval": 64
},
"data": [
["prod", 3.13 ,"Hi"],
["john", 18, "mike"]
]
}
];
var innerDataValues = data.map(element => element.data);
console.log(innerDataValues); //[ [ [ 'test', 3.12, 'Hello' ], [ 'toto', 18, 'titi' ] ], [ [ 'prod', 3.13, 'Hi' ], [ 'john', 18, 'mike' ] ] ]