I'm facing some issue in for loop while creating an object from array of object.I have an array as this in node js app:
[
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
]
I want to return object like this which contains all the Material as array, Name and there value in array of object like this:
{
Material: ["113/133", "150/300"],
datasets: [
{
label: "WELD1",
data: [27520,1441]
},
{
label: "WELD2",
data: [676992,555]
},
{
label: "WELD3",
data: [100,20,0]
}
]
}
I want to get result using for loop.
you can use .reduce() and do something like this:
var arr = [
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
];
var newArr = arr.reduce((acc, ob) => {
for (var key in ob)
if(typeof acc[key] === 'object')
acc[key] = acc[key] ? acc[key].concat(ob[key]) : [ob[key]];
else
acc[key] ? acc[key].push(ob[key]) : acc[key] = [ob[key]];
return acc;
}, {});
console.log(newArr);
let array = [
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
]
let answer = {Material: [], datasets: []}
array.forEach(x => {
answer.Material.push(x.Material);
x.Name.forEach(na => {
let object = answer.datasets.find(obj => obj.label === na.name) || {label: "", data: []};
if(object.label === ""){
object.label = na.name;
object.data.push(na.value);
answer.datasets.push(object);
}else{
object.data.push(na.value)
}
});
});
console.log(answer);
The above is alternative solution using forEach instead of reduce
Use of Array.reduce to build your new data structure using data you have
const start = [{
"Material": "113/133",
"Name": [{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
];
const end = start.reduce((tmp, {
Material,
Name,
}) => {
// Handle the material
// If it do not exist in the array, push it
if (!tmp.Material.includes(Material)) {
tmp.Material.push(Material);
}
// Handle the datasets
// Look at each Name
Name.forEach(({
name,
value,
}) => {
// Can we find the label?
const labelFind = tmp.datasets.find(y => y.label === name);
// If we can't find the label, create a new dataset
if (!labelFind) {
tmp.datasets.push({
label: name,
data: [
value,
],
});
return;
}
// If we has found it push new value in the dataset
labelFind.data.push(value);
});
return tmp;
}, {
Material: [],
datasets: [],
});
console.log(end);
// This is the old fashioned way.
// Iterate over whole array,
// make a map, push value where 'name' is found in map
// later iterate over this map - dataMap - and form required datasets array.
var Material = [];
var dataMap = {};
arr.forEach(obj => {
Material.push(obj.Material);
obj.Name.forEach(item => {
if(dataMap[item.name]){
dataMap[item.name].push(item.value);
}
else {
dataMap[item.name] = [item.value];
}
});
});
var datasets = [];
Object.keys(dataMap).forEach(label => {
datasets.push({
label: label,
data: dataMap[label]
});
});
var result = {
Material: Material,
datasets: datasets
}
console.log(result);
Related
Trying, find and return a value from array using JavaScript- with dynamic inputs
const drawers = [
{
"name": "locations",
"values": [
{
"value": "dana-point-ca",
"label": "Dana Point, CA"
},
{
"value": "bronx-new-york",
"label": "Bronx, New York"
},
{
"value": "new-york-ny",
"label": "New York, NY"
}
]
},
{
"name": "programAreas",
"values": [
{
"value": "coral-conservation",
"label": "CORAL CONSERVATION"
}
]
}
]
Input keys are dynamic, if it is locations and value is bronx-new-york then it should return Bronx, New York;
let lbl = drawers.find(o => o.name === 'string 1').label;
Use array.find in each values until you find the answer.
const drawers = [
{
"name": "locations",
"values": [
{
"value": "dana-point-ca",
"label": "Dana Point, CA"
},
{
"value": "bronx-new-york",
"label": "Bronx, New York"
},
{
"value": "new-york-ny",
"label": "New York, NY"
}
]
},
{
"name": "programAreas",
"values": [
{
"value": "coral-conservation",
"label": "CORAL CONSERVATION"
}
]
}
]
function getLabel(x) {
for (const nameValues of drawers) {
const values = nameValues.values
const item = values.find(v => v.value === x)
if (item !== undefined) {
return item.label
}
}
}
getLabel("bronx-new-york") // 'Bronx, New York'
getLabel("coral-conservation") // 'CORAL CONSERVATION'
getLabel("Value that does not exist") // undefined
for(let i = 0 ; i < drawers.length ; i++){
let lbl = drawers[i].values.find(o => o.label === "Bronx, New York").label;
console.log(lbl)
}
There is a couple of ways to achieve that. As below, you will get all the possible results. However, you might need to deconstruct the arrays in order to get the strings.
const drawers = [
{
"name": "locations",
"values": [
{
"value": "dana-point-ca",
"label": "Dana Point, CA"
},
{
"value": "bronx-new-york",
"label": "Bronx, New York"
},
{
"value": "new-york-ny",
"label": "New York, NY"
}
]
},
{
"name": "programAreas",
"values": [
{
"value": "coral-conservation",
"label": "CORAL CONSERVATION"
}
]
}
]
const enteredValue = "bronx-new-york";
const resultArrays = []
const onSearchLocation = () => {
drawers.find(location => {
const labels = location.values.map((place => {
const array = [];
if(place.value === enteredValue) {
array.push(place.label);
}
if(array.length > 0) {
resultArrays.push(array);
}
}
))
})}
onSearchLocation();
console.log(resultArrays);
I use find with combination of map.
const d = [
{
"name": "locations",
"values": [
{
"value": "dana-point-ca",
"label": "Dana Point, CA"
},
{
"value": "bronx-new-york",
"label": "Bronx, New York"
},
{
"value": "new-york-ny",
"label": "New York, NY"
}
]
},
{
"name": "programAreas",
"values": [
{
"value": "coral-conservation",
"label": "CORAL CONSERVATION"
}
]
}
]
let r = d.find(el => el.name === 'locations').values
let re = r.map(v => {
if (v.value == 'bronx-new-york') {
return v.label
}
})
result = re.filter(e => e)
console.log(result)
Hi I am getting data from API but I want my data in different format so that I can pass later into a function. I want to change the names of keys into a different one becasuse I have created a chart and it only draws if I send it data in certain way
This is what I am getting from API
data = {
"status": "success",
"from": "DB",
"indice": "KSE100",
"data": [
{
"stock_sector_name": "Tc",
"sector_score": "0828",
"stocks": [
{
"stock_symbol": "TRG",
"stock_score": 44
},
{
"stock_symbol": "SYS",
"stock_score": 33
}
]
},
{
"stock_sector_name": "OIL",
"sector_score": "0828",
"stocks": [
{
"stock_symbol": "FFS",
"stock_score": 44
},
{
"stock_symbol": "SMS",
"stock_score": 33
}
]
},
]
}
But I want my data to look like this like this
data = {
"name": "KSE100",
"children": [
{
"name": "A",
'points': -9,
"children": [
{
"stock_title": "A",
"value": 12,
},
{
"stock_title": "B",
"value": 4,
},
]
},
{
"name": "B",
'points': 20,
"children": [
{
"stock_title": "A",
"value": 12,
},
{
"name": "B",
"value": 4,
},
]
},
]
}
Like I want to replace
stock_sector_name = name
sector_score = value
stocks = children
stock_symbol = name
stock_score = value
I have been trying this for so much time but sill could not figured it out
function convert(d){
return {
name : d.indice,
children : d.data.map(y=>{
return {
name : y.stock_sector_name,
points : y.sector_score,
children : y.stocks.map(z=>{
return {
stock_title: z.stock_symbol,
value : z.stock_score
}
})
}
})
}
}
You can do something like this
const data = {
"status": "success",
"from": "DB",
"indice": "KSE100",
"data": [{
"stock_sector_name": "Tc",
"sector_score": "0828",
"stocks": [{
"stock_symbol": "TRG",
"stock_score": 44
},
{
"stock_symbol": "SYS",
"stock_score": 33
}
]
},
{
"stock_sector_name": "OIL",
"sector_score": "0828",
"stocks": [{
"stock_symbol": "FFS",
"stock_score": 44
},
{
"stock_symbol": "SMS",
"stock_score": 33
}
]
},
]
}
const data2 = {
"name": "KSE100",
"children": [{
"name": "A",
'points': -9,
"children": [{
"stock_title": "A",
"value": 12,
},
{
"stock_title": "B",
"value": 4,
},
]
},
{
"name": "B",
'points': 20,
"children": [{
"stock_title": "A",
"value": 12,
},
{
"name": "B",
"value": 4,
},
]
},
]
}
//stock_sector_name = name
//sector_score = value
//stocks = children
//stock_symbol = stock_title
//stock_score = value
const keys = {
stock_sector_name: "name",
sector_score: "points",
stocks: "children",
stock_symbol: "stock_title",
stock_score: "value",
indice: "name",
//data: "children"
}
const rename = (value) => {
if (!value || typeof value !== 'object') return value;
if (Array.isArray(value)) return value.map(rename);
return Object.fromEntries(Object
.entries(value)
.map(([k, v]) => [keys[k] || k, rename(v)])
);
}
renamedObj = rename(data);
console.log(renamedObj);
I have an object that looks like the following {key: id numbers}
var obj = {
"c4ecb": {id: [3]},
"a4269": {id: [34,36]},
"d76fa": {id: [54,55,60,61]},
"58cb5": {id: [67]}
}
How do I loop each above id in the following array, and return the label?
var response =
{
"success": true,
"data": [
{
"key": "c4ecb",
"name": "fruits",
"options": [
{
"label": "strawberry",
"id": 3
},
{
"label": "apple",
"id": 4
},
{
"label": "pineapple",
"id": 5
},
{
"label": "Other",
"id": 31
}
],
}
]
},
{
"success": true,
"data": [
{
"key": "a4269",
"name": "vegetables",
"options": [
{
"label": "lettuce",
"id": 34
},
{
"label": "cucumber",
"id": 35
},
{
"label": "radish",
"id": 36
}
],
}
]
},
{
"success": true,
"data": [
{
"key": "d76fa",
"name": "pasta",
"options": [
{
"label": "spaghetti",
"id": 54
},
{
"label": "rigatoni",
"id": 55
},
{
"label": "linguine",
"id": 56
},
{
"label": "lasagna",
"id": 60
},
{
"label": "fettuccine",
"id": 61
}
],
}
]
}
Finally, what I want to do is look up the key and return a string of id values.
For example, input c4ecb and output strawberry. Input a4269 and output lettuce, radish. Input d76fa and output "spaghetti, rigatoni, lasagna, fettuccine"
I think to join the multiple labels output into one string I could use something like
array.data.vegetables.map(vegetables => vegetables.value).join(', ')].toString();
So in the end I want to have something like
var fruits = [some code that outputs "strawberry"];
var vegetables = [some code that outputs "lettuce, radish"];
var pasta = [some code that outputs "spaghetti, rigatoni, lasagna, fettuccine"];
What I've tried so far:
The following loop will return the id only if there is one id to be called for: e.g. only in case one where {id: 3} but returns null in cases like {id: 34,36} (because it's looking for '34,36' in id, which doesn't exist - I need to look for each one individually.
response.data.forEach(({key, options}) => {
if (obj[key]) {
options.forEach(({id, label}) => {
if (id == obj[key].id) obj[key].label = label;
});
}
});
console.log(obj)
Filter the response object to focus on the category that matches the id.
Map over the options array and select the items which appear in obj[id].
Finally convert the filtered results to a string.
See filteredLabelsAsString() function below for implementation.
var obj = {
"c4ecb": {"id": [3]},
"a4269": {"id": [34,36]},
"d76fa": {"id": [54,55,60,61]},
"58cb5": {"id": [67]}
}
var response =
[{
"success": true,
"data": [
{
"key": "c4ecb",
"name": "fruits",
"options": [
{
"label": "strawberry",
"id": 3
},
{
"label": "apple",
"id": 4
},
{
"label": "pineapple",
"id": 5
},
{
"label": "Other",
"id": 31
}
],
}
]
},
{
"success": true,
"data": [
{
"key": "a4269",
"name": "vegetables",
"options": [
{
"label": "lettuce",
"id": 34
},
{
"label": "cucumber",
"id": 35
},
{
"label": "radish",
"id": 36
}
],
}
]
},
{
"success": true,
"data": [
{
"key": "d76fa",
"name": "pasta",
"options": [
{
"label": "spaghetti",
"id": 54
},
{
"label": "rigatoni",
"id": 55
},
{
"label": "linguine",
"id": 56
},
{
"label": "lasagna",
"id": 60
},
{
"label": "fettuccine",
"id": 61
}
],
}
]
}];
function filteredLabelsAsString(obj_key, obj, content=response) {
// sanity check: obj must contain obj_key
if (Object.keys(obj).includes(obj_key)) {
return content.filter((item) => {
// filter content using value of obj_key
return item.data[0].key == obj_key;
}).map((item) => {
// item : { success: true, data: [] }
// map over options array
return item.data[0].options.map((opt) => {
// option : {id, label}
// return the label if the id is in the obj object's list
if (obj[item.data[0].key].id.includes(opt.id))
return opt.label;
}).filter((label) => {
// filter out empty items
return label !== undefined;
});
}).join(",");
}
// if obj does not contain obj_key return empty string
return "";
}
console.log("fruits: " + filteredLabelsAsString("c4ecb", obj));
console.log("vegetables: " + filteredLabelsAsString("a4269", obj));
console.log("pasta: " + filteredLabelsAsString("d76fa", obj));
So in the API response example below, focusing on env_variables, I am trying grab the value for secret. I am stuck because as you can see, the name and value are not nested together. I am not familiar with how to grab the value based on the name in this example.
api response:
{
"id": 1146,
"job": {
"name": "jobname1",
},
"env_variables": [
{
"name": {
"name": "test1"
},
"value": {
"value": "10.13.6"
}
},
{
"name": {
"name": "test1"
},
"value": {
"value": "10.13.6"
}
},
],
},
{
"id": 1147,
"job": {
"name": "jobname2",
},
"env_variables": [
{
"name": {
"name": "secret"
},
"value": {
"value": "10.13.7"
}
},
{
"name": {
"name": "test5"
},
"value": {
"value": "10.13.6"
}
},
],
}
js
jobs: []
apiEndpoint = "test.com/api"
fetch(this.apiEndpoint)
.then(response => response.json())
.then(body => {
for(let i=0; i<body.length; i++){
this.jobs.push({
'build_id': JSON.stringify(body[i].id),
'secret': //not sure how to pull the value (10.13.7)
})
}
})
You need nested loops, since there are two nested arrays: the top level of the response is an array of objects, and env_variables contains an array of objects.
fetch(this.apiEndpoint)
.then(response => response.json())
.then(body => {
for (let i = 0; i < body.length; i++) {
let env = body[i].env_variables;
for (let j = 0; j < env.length; j++) {
if (env[j].name.name == "secret") {
this.jobs.push({
'build_id': JSON.stringify(body[i].id),
'secret': env[j].value.value
})
}
}
}
})
You can do something like this inside .then(body=>...
const body = [{ //it looks like brackets [] were lost in OP
"id": 1146,
"job": {
"name": "jobname1",
},
"env_variables": [{
"name": {
"name": "test1"
},
"value": {
"value": "10.13.6"
}
},
{
"name": {
"name": "test1"
},
"value": {
"value": "10.13.6"
}
},
],
},
{
"id": 1147,
"job": {
"name": "jobname2",
},
"env_variables": [{
"name": {
"name": "secret"
},
"value": {
"value": "10.13.7"
}
},
{
"name": {
"name": "test5"
},
"value": {
"value": "10.13.6"
}
},
],
}
];
let secret = null;
body.forEach(b => {
let el = b.env_variables.find(e => e.name.name == 'secret');
if (el) { //found
secret = el.value.value;
return false; //exit forEach
}
});
console.log(secret);
You could also do something like this with Array.forEach and Array.find:
let data = [{ "id": 1146, "job": { "name": "jobname1", }, "env_variables": [{ "name": { "name": "test1" }, "value": { "value": "10.13.6" } }, { "name": { "name": "test1" }, "value": { "value": "10.13.6" } }, ], }, { "id": 1147, "job": { "name": "jobname2", }, "env_variables": [{ "name": { "name": "secret" }, "value": { "value": "10.13.7" } }, { "name": { "name": "test5" }, "value": { "value": "10.13.6" } }, ], } ]
let jobs = []
data.forEach(({id, env_variables}) => jobs.push({
build_id: id,
secret: ((env_variables.find(({name}) =>
name.name === 'secret') || {}).value || {}).value || 'N/A'
// ... other props
}))
console.log(jobs)
Assuming your result is an array, you could do something like this:
let secrets = results.reduce((result, item) => {
let secret = item["env_variables"].find((v) => {return v.name.name === "secret"})
if(secret){
result.push({id:item.id, secret: secret.value.value});
}
return result;
}, []);
This would return an array of objects like {id: 1, secret: ""} for each object in your result set that has a secret.
If you don't care whether the secret is present or not, you could modify the code slightly like this:
let secrets = results.reduce((result, item) => {
let secret = item["env_variables"].find((v) => {return v.name.name === "secret"})
result.push({id:item.id, secret: secret ? secret.value.value : ""});
return result;
}, []);
Which just leaves with you an empty string on the levels where there is no secret.
i have this data structure:
tree = [
{
"name": "Men Section",
"categories": [
{
"name": "Clothings",
"Subcategories": [
{
"name": "Jackets",
"products": [
{
"name": "jacket 01",
"price": 100
},
{
"name": "jacket 02",
"price": 140
},
// ..and so on
]
]
},
// ..and so on
]
} // ..and so on
]
how can i add new property in products item isSelected: false in javascript (ES5 or ES6 is fine) so the object will be
{
"name": "jacket 01",
"price": 100,
"isSelected": false
}
?
It could be useful, it works for me
tree.forEach(base => {
base.categories.forEach(categories => {
categories.Subcategories.forEach(subCategory =>{
subCategory.products.forEach(product => product.isSelected = false)
})
});
});
so yeah, i should traverse deep to the object with nested foreach. i came up with this:
tree.categories.forEach(function (category) {
category.subcategories.forEach(function (subcategory) {
subcategory.products.forEach(function (product) {
product.isSelected = false;
})
})
})
thanks for the enlightment