this is the array that i currently have
const myArr = [
{
"code": {
"value": "AC16",
"description": "text"
},
"convictionDate": {
"value": "2019-03-07"
}
},
{
"code": {
"value": "AC20",
"description": "text"
},
"convictionDate": {
"value": "2019-03-06"
}
}
];
I want to map over each nested object inside the array so that the value of each nested object is the value property of that object as a string. so the object would become:
const myArr = [
{
"code": "AC16",
"convictionDate":"2019-03-07"
},
{
"code":"AC20",
"convictionDate": "2019-03-06"
}
]
Ive tried this with no success:
const x = myArr.map((item)=>{
console.log(item)
Object.keys(item).map(function(key,i) {
item[key] = item[key][value];
})
})
You are almost there. Just use array map
const myArr = [{
"code": {
"value": "AC16",
"description": "text"
},
"convictionDate": {
"value": "2019-03-07"
}
},
{
"code": {
"value": "AC20",
"description": "text"
},
"convictionDate": {
"value": "2019-03-06"
}
}
];
let newArray = myArr.map(function(item) {
return {
code: item.code.value,
convictionDate: item.convictionDate.value
}
});
console.log(newArray)
Map the array, and reduce the entries to the required object form:
const myArr = [{"code":{"value":"AC16","description":"text"},"convictionDate":{"value":"2019-03-07"}},{"code":{"value":"AC20","description":"text"},"convictionDate":{"value":"2019-03-06"}}];
const result = myArr.map(o =>
Object.entries(o).reduce((r, [k, { value }]) => ({ ...r, [k]: value }), {})
);
console.log(result);
const myArr = [
{
"code": {
"value": "AC16",
"description": "text"
},
"convictionDate": {
"value": "2019-03-07"
}
},
{
"code": {
"value": "AC20",
"description": "text"
},
"convictionDate": {
"value": "2019-03-06"
}
}
];
let newArray = myArr.map(e => {
return { "code":e.code.value, "convictionDate": e.convictionDate.value}
})
console.log(newArray);
It goes without saying there is some awesome reference material over at W3 Schools, the provide good detail on this in their article here
That said...
Why not simplify the code a little and try this against your array:-
const myArr = [
{
"code": {
"value": "AC16",
"description": "text"
},
"convictionDate": {
"value": "2019-03-07"
}
},
{
"code": {
"value": "AC20",
"description": "text"
},
"convictionDate": {
"value": "2019-03-06"
}
}
];
// PROPOSED SOLUTION CODE
const x = myArr.map((item)=>{
return {code: item.code.value,convictionDate: item.convictionDate.value}
});
// Your Desired Example Provided in Question
const xArr = [
{
"code": "AC16",
"convictionDate":"2019-03-07"
},
{
"code":"AC20",
"convictionDate": "2019-03-06"
}
];
// Output Validation
console.log('Response of Array \'x\'');
console.log(x);
console.log('Your Desired Example');
console.log(xArr);
When using 'map'; we must map the source array ('myArr') to our new target array ('x').
In the context of the example code you have provided, 'data.convictions' is undefined.
The magic is all here:-
const x = myArr.map((item)=>{
return {code: item.code.value,convictionDate: item.convictionDate.value}
});
Happy coding!
Related
How to combine JSON objects in the same response that has the same key and value with javascript? This is my data for example:
{
"data": [
{
"name": "A",
"description": {
"location": "location1",
"floor": "floor1",
},
},
{
"name": "A",
"description": {
"location": "location2",
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
}
And turn it into this:
{
"data": [
{
"name": "A",
"description": {
"location": ["location1","location2"],
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
}
Basically I am someone who is new to learning javascript. Any help would be very helpful, thank you.
You can do:
const data = {data: [{name: 'A',description: {location: 'location1',floor: 'floor1',},},{name: 'A',description: {location: 'location2',floor: 'floor1',},},{name: 'B',description: {location: 'location3',floor: 'floor3',},},],}
const result = {
data: data.data.reduce((a, { name, description }) => {
const index = a.findIndex((d) => d.name === name)
if (index >= 0) {
let location = a[index].description.location
location = Array.isArray(location) ? location : [location]
a[index].description.location = [...location, description.location]
} else {
a.push({ name, description })
}
return a
}, []),
}
console.log(result)
const list = {
"data": [
{
"name": "A",
"description": {
"location": "location1",
"floor": "floor1",
},
},
{
"name": "A",
"description": {
"location": "location2",
"floor": "floor1",
},
},
{
"name": "B",
"description": {
"location": "location3",
"floor": "floor3",
},
},
]
};
const consolidatedData = [];
for (const ele of list.data) {
const isExist = consolidatedData.find(x => x.name === ele.name);
if (!isExist) {
consolidatedData.push({
...ele
})
} else {
const objectKey = consolidatedData.findIndex(x => x.name === ele.name);
if (objectKey > -1) {
const description = consolidatedData[objectKey].description;
const newDes = ele.description;
if (newDes.location !== description.location) {
const data = consolidatedData[objectKey].description;
const added = [data.location, ele.description.location];
delete consolidatedData[objectKey].description.location
consolidatedData[objectKey].description["location"] = added
}
if (newDes.floor !== description.floor){
const data = consolidatedData[objectKey].floor;
const added = [data.floor, ele.description.floor];
delete consolidatedData[objectKey].description.floor
consolidatedData[objectKey].description["floor"] = added
}
}
}
}
console.log(JSON.stringify(consolidatedData, null, 2));
Here is a solution that uses an intermediate bucket object. The desired result object is then constructed from the bucket object:
const input = { "data": [ { "name": "A", "description": { "location": "location1", "floor": "floor1", }, }, { "name": "A", "description": { "location": "location2", "floor": "floor1", }, }, { "name": "B", "description": { "location": "location3", "floor": "floor3", }, }, ] };
let buckets = input.data.reduce((acc, obj) => {
if(!acc[obj.name]) {
acc[obj.name] = {
locations: {},
floors: {}
};
}
acc[obj.name].locations[obj.description.location] = true;
acc[obj.name].floors[obj.description.floor] = true;
return acc;
}, {});
console.log('buckets: ', buckets);
let result = {
data: Object.keys(buckets).map(name => {
let locations = Object.keys(buckets[name].locations);
let floors = Object.keys(buckets[name].floors);
return {
name: name,
description: {
location: locations.length == 1 ? locations[0] : locations,
floor: floors.length == 1 ? floors[0] : floors
}
}
})
};
console.log('result:', result);
Notes:
buckets object:
is created using an array .reduce()
array .reduce() docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
locations and floors are collected using objects instead of arrays, this is to avoid duplicate names
result object:
is using Object.keys(buckets) to get the array of names
.map() transforms each name into the desired object
your unusual array or string value for location and floor is constructed with a conditional
I need to put the images that are on "included" into "data:{relationships: { field_imagen: { data" but the problem is that i just managed to put only the first image into every index using map and find
noticiasImages.forEach(function(data: { relationships: { field_imagen: {data: {id:any}}}} ) {
var nestedArray = noticiasData.map((noticiasImages: { id: any; }) => noticiasImages == noticiasData);
data = nestedArray && noticiasImages || noticiasData;
});
And this is my json (example node)
{
"data": [
"relationships": {
"field_imagen": {
"data": [
{
"type": "file--file",
"id": "dba917f0-b80f-45ed-a569-69f2ba2b482d",
}
],
}
]
},
this is the included object, who is in the same level as data
"included": [
"attributes": {
"drupal_internal__fid": 8798,
"langcode": "es",
"filename": "_DSC6472 - copia.jpg",
"uri": {
"value": "public:\/\/2019-11\/_DSC6472 - copia.jpg",
"url": "\/sites\/default\/files\/2019-11\/_DSC6472%20-%20copia.jpg"
},
},
,
Expected Result:
"data": [
"relationships": {
"type": "node--actualidad_institucional",
"id": "71514647-af49-4136-8a28-9563d133070a",
"field_imagen": {
"data": [
{
"type": "file--file",
"id": "dba917f0-b80f-45ed-a569-69f2ba2b482d",
"uri": {
"value": "public:\/\/2019-11\/_DSC6472 - copia.jpg",
"url": "\/sites\/default\/files\/2019-11\/_DSC6472%20-%20copia.jpg"
},
}
}
},
I put the uri from included into field_imagen. Tried to resolve like that, but it just put only the first image of the Array from the included object in every node:
showNoticias() {
this.frontService.getNoticias()
.subscribe((data: Noticias) => {
this.noticiasImages = Array.from(data.included);
this.noticiasData = Array.from(data.data);
let noticiasImages = this.noticiasImages.map((data: {id: any}) => data.id);
let noticiasData = this.noticiasData.map((data:{relationships: { field_imagen: { data: { id: any; }}}}) => data.relationships.field_imagen.data.id);
noticiasImages.forEach(function(data: { relationships: { field_imagen: {data: {id:any}}}} ) {
var nestedArray = noticiasData.map((noticiasImages: { id: any; }) => noticiasImages == noticiasData);
data = nestedArray && noticiasImages || noticiasData;
});
console.log(data);
});
}
Hope you can help me, thanks!
UPDATE: tried that but didnt work like expected
let merged = data.data.map((data:{relationships: { field_imagen: { data: any }}}) => Object.assign({}, noticiasImages));
console.log(data)
console.log(merged)
Sometimes using regular for loops are a better option. Using map with objects that have that many properties can get confusing. And using forEach will not give you access to the i index of the iteration in the loop, which makes things easier in this case.
for (let i = 0; i < obj.included.length; i++) {
let uri = obj.included[i].attributes.uri;
obj.data[i].relationships.field_imagen.data[0] = {
...obj.data[i].relationships.field_imagen.data[0],
...uri
}
}
console.log(obj)
Output:
{
"data": [
{
"relationships": {
"field_imagen": {
"data": [
{
"type": "file--file",
"id": "dba917f0-b80f-45ed-a569-69f2ba2b482d",
"value": "public://2019-11/_DSC6472 - copia.jpg",
"url": "/sites/default/files/2019-11/_DSC6472%20-%20copia.jpg"
}
]
}
}
}
],
"included": [
{
"attributes": {
"drupal_internal__fid": 8798,
"langcode": "es",
"filename": "_DSC6472 - copia.jpg",
"uri": {
"value": "public://2019-11/_DSC6472 - copia.jpg",
"url": "/sites/default/files/2019-11/_DSC6472%20-%20copia.jpg"
}
}
}
]
}
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 currently have an existing JSON that I want to change/reformat into a new JSON to be able to be used in an external service. The format is a bit complicated but I can't change it, so I have to edit my existing JSON. to match my desired output.
Existing JSON:
{
"specifiers": [{
"value": "test",
"type": "text",
"label": "Brand ID"
}, {
"value": "test",
"type": "text",
"label": "Program ID"
}]
}
Desired Output:
{
"specifiers": {
"Brand ID": {
"text": {
"value": "test",
"type": "text"
}
},
"Program ID": {
"text": {
"value": "test",
"type": "text"
}
}
}
}
I've tried iterating through the existing JSON using loops, but I don't really know how to format my loops to use the values as the keys? I'm guessing that I might have to use Object.keys or Object.values, but I'm not sure how to get a specific value for a specific key.
Example Format:
"[label]": {
"[type]": {
"value": [value],
"type": [type]
}
}
function tranform({specifiers}) {
return { specifiers: specifiers.reduce((obj, {label, type, value}) => ({...obj, [label]: { [type]: { type, value } } }), {}) }
}
const json = {
"specifiers": [{
"value": "test",
"type": "text",
"label": "Brand ID"
}, {
"value": "test",
"type": "text",
"label": "Program ID"
}]
}
console.log(tranform(json))
Pretty straightforward with a reduce:
const formattedSpecifiers = existingJSON.specifiers.reduce((newSpecifiers, specifier) => {
newSpecifiers[specifier.label] = {
[specifier.type]: {
type: specifier.type,
value: specifier.value,
},
};
};
return newSpecifiers;
}, {});
const newJSON = { specifiers: formattedSpecifiers };
you can use #Array.reduce. snippet below.
let input = {
"specifiers": [{
"value": "test",
"type": "text",
"label": "Brand ID"
}, {
"value": "test",
"type": "text",
"label": "Program ID"
}]
}
const res = input.specifiers.reduce((res, obj) => {
const {
label,
type,
value
} = obj
res[label] = {};
res[label][type] = {
value,
type
};
return res;
}, {});
console.log(res);
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);