Getting empty data while trying to get desired format of object - javascript

I have an object
"data" : [
{
"name" : "Heading",
"text" : "Text Heading",
"type" : "string",
"values" : [
"Arthur"
]
},
{
"name" : "Source",
"text" : "Source Reference",
"type" : "string",
"values" : [
"Jhon"
]
},
{
"name" : "Place",
"text" : "Bank Building",
"type" : "string",
"values" : [
"Mark"
]
},
{
"name" : "Animal",
"text" : "Branch",
"type" : "string",
"values" : [
"Susan"
]
}
]
there is a function i am passing the object and an array as the arguments
fieldArray=["Heading", "Animal"]
myFunction(fieldArray, data){
... your code here
}
I need to get the output in the below format where I have to search the object with the fields in myArray with the name key of data. Then I need to put the value of the searched object in the below format
[{
"id": 1,
"cells": [{
"id": "ConstId",
"cellContent": "Heading"
},
{
"id": "ConstValue",
"cellContent": "Arthur"
}
]
},
{
"id": 2,
"cells": [{
"id": "ConstId",
"cellContent": "Animal"
},
{
"id": "ConstValue", //a constant field name as ConstValue
"cellContent": "Susan" // the value of the second field in the myArray from object with name Animal
}
]
}
]
I have tried this
const getFormattedData = (fieldArray: any, data: any) => {
let innerData: any = [];
for (let i=0; i<fieldArray.length; i++){
const indexNumber = data.find((key: any) => key.name === fieldArray[i])
if(indexNumber != undefined){
innerData.push({
id: i+1,
cells:[{
id: 'inquiryName',
cellContent: indexNumber.name
},
{
id: 'value',
cellContent: indexNumber.values.toString()
}
]
})
}
console.log('innerData :>> ', innerData);
}
}

You could use the below. Since you tagged javascript, posting answer in JS.
function formatData(data, fieldArray) {
let ret = [];
fieldArray.forEach((field, i) => {
let dataObj = data.filter(d => d.name === field)[0]
if( dataObj ) {
ret.push({
"id": 1,
"cells": [{
"id": "ConstId",
"cellContent": field
},
{
"id": "ConstValue",
"cellContent": dataObj.values[0] //Put whole obj or just first
}
]
})
}
})
return ret;
}
Link to plnkr

Related

I want to compare inner array in JSON array of object and return new array depending on condition using JavaScript

I have following array of object
let studentArray =
[{
"name" : "Computer Science",
"students" : [
{
"student_name" : "A"
},
{
"student_name" : "B"
}
]
},
{
"name" : "Math",
"students" : [
{
"student_name" : "A"
},
{
"student_name" : "B"
},
{
"student_name" : "C"
}
]
}]
and I want answer like below.
[
{
"student_name" : "A",
"courses": ["Computer Science", "Math"]
},
{
"student_name" : "B",
"courses": ["Computer Science", "Math"]
},
{
"student_name" : "C",
"courses": ["Math"]
}
]
Please help with javascript functionality and according to data structure algorithm.
I have tried below it is not working.
I there any another way to doing this Using different another loops or something another logic for that.
let studentArray = [{
"name": "Computer Science",
"students": [{
"student_name": "A"
},
{
"student_name": "B"
}
]
},
{
"name": "Math",
"students": [{
"student_name": "A"
},
{
"student_name": "B"
},
{
"student_name": "C"
}
]
}
]
studentArray.forEach((item, index) => {
//console.log(item);
if (index > 0) {
console.log("Previous: " + studentArray[index - 1].students);
}
if (index < studentArray.length - 1) {
console.log("Next: " + studentArray[index + 1].students);
}
//console.log(studentArray);
console.log(item.students.filter(comparer(item.students)));
});
function comparer(otherArray) {
return function(current) {
return otherArray.filter(function(other) {
return other.value == current.value && other.display == current.display
}).length == 0;
}
}
You can use Array.reduce() on the studentArray to group students with their courses.
We create an object keyed by student name and iterate over each course's student array to add students to the map (using for...each).
Finally, we use Object.values() to turn our map into an array:
const studentArray = [{ "name" : "Computer Science", "students" : [ { "student_name" : "A" }, { "student_name" : "B" } ] }, { "name" : "Math", "students" : [ { "student_name" : "A" }, { "student_name" : "B" }, { "student_name" : "C" } ] }];
const result = Object.values(studentArray.reduce((acc, course) => {
for(let student of course.students) {
let student_name = student.student_name;
acc[student_name ] = acc[student_name ] || { student_name , courses: []};
acc[student_name ].courses.push(course.name);
}
return acc;
}, {}))
console.log(result)
Use a nested forEach loop
const studentArray = [{
name: "Computer Science",
students: [{
student_name: "A"
},
{
student_name: "B"
}
]
},
{
name: "Math",
students: [{
student_name: "A"
},
{
student_name: "B"
},
{
student_name: "C"
}
]
}
];
const newArr = [];
studentArray.forEach((c) => {
c.students.forEach((s) => {
let studentIndex = newArr.findIndex(el => el.student_name === s.student_name);
studentIndex === -1 ? newArr.push({
student_name: s.student_name,
courses: [c.name]
}) : newArr[studentIndex].courses.push(c.name)
})
})
console.log(newArr);
Another approach using reduce, map, and some ES6 spread syntax:
const courses = [
{
"name" : "Computer Science",
"students" : [{ "student_name" : "A" }, { "student_name" : "B" }]
},
{
"name" : "Math",
"students" : [{ "student_name" : "A" }, { "student_name" : "B" }, { "student_name" : "C" }]
}
]
// Add students from a course to an array if they're not present already
const selectUniqueStudents = (currentStudentList, course) =>
currentStudentList.concat(course.students.filter(newStudent =>
currentStudentList.every(
currentStudent => currentStudent.student_name !== newStudent.student_name
)
))
// Add each course that the student is on to an array and append to the
// student object
const addCourseDetails = (student) => ({
...student,
courses: courses
.filter(course =>
course.students.some(courseStudent => courseStudent.student_name === student.student_name)
)
.map(course => course.name)
})
const transformedResult = courses
.reduce(selectUniqueStudents, [])
.map(addCourseDetails)
console.log(transformedResult)
// Returns:
//
// [
// { student_name: 'A', courses: [ 'Computer Science', 'Math' ] },
// { student_name: 'B', courses: [ 'Computer Science', 'Math' ] },
// { student_name: 'C', courses: [ 'Math' ] }
// ]
Same as with Vineet's answer, Terry's would run faster. This is not as concise or easy to read either. But the demonstration of aggregate array functions and ES6 syntax might be useful.

How to transform this specific js array into js object?

I have one javascript array got from back end api, for convenience, need to be sort into the form of below, described as final target.
But I don't know how to start. Anyone can help?
The original src array is like below :
var src = [
{
"parent_kind" : "Animal",
"name" : "Cow"
},
{
"name" : "Animal"
},
{
"parent_kind" : "Animal",
"name" : "Dog"
},
{
"parent_kind" : "Animal",
"name" : "Horse"
},
{
"name" : "Vehicle"
},
{
"parent_kind" : "Vehicle",
"name" : "Bus"
},
{
"parent_kind" : "Bus",
"name" : "Shuttle"
},
]
The final target is :
{
"Vehicle" : {
"Bus" : {
"Shuttle" : {}
}
},
"Animal" : {
"Cow" : {},
"Dog" : {},
"Horse" : {}
}
}
I can got each element of the original array by
for (let ele of src) {
console.log(ele)
}
you can do that with a simple Array.reduce() method
var src =
[ { parent_kind: 'Animal', name: 'Cow' }
, { name: 'Animal' }
, { parent_kind: 'Animal', name: 'Dog' }
, { parent_kind: 'Animal', name: 'Horse' }
, { name: 'Vehicle' }
, { parent_kind: 'Vehicle', name: 'Bus' }
, { parent_kind: 'Bus', name: 'Shuttle' }
]
let res = src.reduce((a,{parent_kind,name},i)=>
{
if(!!parent_kind)
{
let np = a.p.find(x=>x.pN===parent_kind)
if(!np)
{
a.r[parent_kind] = {}
np = {pN:parent_kind, e:a.r[parent_kind]}
a.p.push( np )
}
let z = np.e[name] = {}
a.p.push( {pN:name, e:z} )
}
return (i===a.len)? a.r : a
}
,{len:src.length-1,r:{},p:[]})
console.log( res )
.as-console-wrapper { max-height: 100% !important; top: 0; }
if you can ok with loop the src many times :-( That's performance is not a concern.
var src = [{
"parent_kind": "Animal",
"name": "Cow"
},
{
"name": "Animal"
},
{
"parent_kind": "Animal",
"name": "Dog"
},
{
"parent_kind": "Animal",
"name": "Horse"
},
{
"name": "Vehicle"
},
{
"parent_kind": "Vehicle",
"name": "Bus"
},
{
"parent_kind": "Bus",
"name": "Shuttle"
},
];
const fn = (source, result, parent) => {
const children = source.filter(({
parent_kind
}) => parent_kind === parent).map(({
name
}) => name);
children.forEach(c => result[c] = {});
children.forEach(c => fn(source, result[c], c));
}
result = {};
fn(src, result)
console.log(result);

How to display all fields of a nested json in table format using Bootstrap

I want to write a utility which connects to a REST api downloads data in JSON format and then paints the data as nested tables using Bootstrap.
JSON Data -
[
{
"id" : "Id1",
"name" : "Name1",
"orders" : [{"orderId" : "o1", "size" : 34}, {"orderId" : "o2", "size" : 3}]
},
{
"id" : "Id2",
"name" : "Name2",
"orders" : [
{"orderId" : "o3", "size" : 5, "addresses" : [{"addressId" : "a1", "phone" : "1235"}, {"addressId" : "a2", "phone" : 555}]},
{"orderId" : "o4", "size" : 5, "addresses" : [{"addressId" : "a3", "phone" : "1235"}]}
]
}
]
I looked at the sub-table feature of Bootstrap, however it seems that it would need lot of custom code to get this working. Is there a better way to bind the json to table in a generic way?
Edit
After spending some time I was able to achieve this -
As you can see, I could get one level of nesting, however i just need to go one level deep. Any suggestions?
<script>
var $table = $('#table')
function buildTable($el, jsonData) {
var i; var j; var row
var columns = []
var data = []
if(!Array.isArray(jsonData) && jsonData.length == 0) {
return;
}
Object.keys(jsonData[0]).forEach( (k) => {
columns.push({
field: k,
title: k,
sortable: true
})
})
for(var j = 0; j < jsonData.length; j++) {
row = {}
Object.keys(jsonData[j]).forEach( (k) => {
row[k] = jsonData[j][k]
})
data.push(row)
}
$el.bootstrapTable({
columns: columns,
data: data,
detailFilter: function (index, row) {
console.log("detail filter " + Object.values(row))
for(var k in row) {
if(Array.isArray(row[k])){
return true;
}
}
return false;
},
onExpandRow: function (index, row, $detail) {
console.log("expand row keys " + Object.keys(row))
console.log("expand row vals " + Object.values(row))
var newRow = {};
for(var k in row) {
if(Array.isArray(row[k])){
alert('found ' + row[k])
newRow = row[k]
break
}
}
buildTable($detail.html('<table></table>').find('table'), newRow)
}
})
};
var mydata =
[
{
"id": 0,
"name": "test0",
"price": "$0",
"orders" :
[
{
"name" : "ABC",
"size" : 25,
"someList": [{"a":1, "b":2}, {"a":3, "b":4}]
},
{
"name" : "XYZ",
"size" : 50
}
]
}
/* {
"id": 1,
"name": "test1",
"price": "$1"
},
{
"id": 2,
"name": "test2",
"price": "$2",
"orders" : [{"name" : "def", "size": 45}]
}*/
];
$(function() {
buildTable($table, mydata)
})

Looping Through Nested JSON with Nested Child Searches

I have a JSON structure that looks like this:
"benefitValues" : [ {
"changeDate" : "2017-10-13T20:26:13.000+0000",
"changeUserName" : "aaaa",
"numericValue" : 20,
"value" : "20",
"amountType" : {
"allowCustomDataFlg" : false,
"dataType" : "Percent",
"defaultTypeFlg" : true,
"defaultValue" : "Unlimited",
"description" : null,
"maxValue" : null,
"minValue" : null,
"name" : "LIST",
"benefit" : {
"category" : "Facility Services",
"name" : "Single Limit",
"networkStatus" : "IN_NETWORK",
"planType" : "MedicalPlan",
"sortOrder" : 20,
"subcategory" : "Acupuncture Treatment",
"subcategorySortOrder" : 6
}
}
}]
Based on the string "Acupuncture Treatment", I need to extract the the value and the datatype. The dataset is very large, with hundreds of subcategories. I cannot find a good way to search through this data. I tried json-path and advanced-json-path, but if I do a search on a child element, there is no way for me to return the parents. I want my output to look like this:
{
"Subcategory" : "Acupuncture Treatment",
"Value" : "20",
"Type" : "Percent"
}
I was hoping there was an easy way to do this with an existing library, or at least with a simple loop.
This will find the matching element frombenefitValues, and transform the element into the format you're expecting:
var benefitValues = [{
"changeDate": "2017-10-13T20:26:13.000+0000",
"changeUserName": "aaaa",
"numericValue": 20,
"value": "20",
"amountType": {
"allowCustomDataFlg": false,
"dataType": "Percent",
"defaultTypeFlg": true,
"defaultValue": "Unlimited",
"description": null,
"maxValue": null,
"minValue": null,
"name": "LIST",
"benefit": {
"category": "Facility Services",
"name": "Single Limit",
"networkStatus": "IN_NETWORK",
"planType": "MedicalPlan",
"sortOrder": 20,
"subcategory": "Acupuncture Treatment",
"subcategorySortOrder": 6
}
}
}];
// Find the element
let treatment = benefitValues.find((item) => item.amountType.benefit.subcategory === 'Acupuncture Treatment');
let result = {
Value: treatment.value,
Subcategory: treatment.amountType.benefit.subcategory,
Type: treatment.amountType.dataType
}
console.log(result);
You can search through your data set and pull out only the items that match your string by using .filter. That would give you the entire object, so then you can use .map to transform it to the structure you want.
Or if you're only interested in the first result, you can use .find instead.
const json = {"benefitValues" : [{
"changeDate" : "2017-10-13T20:26:13.000+0000",
"changeUserName" : "aaaa",
"numericValue" : 20,
"value" : "20",
"amountType" : {
"allowCustomDataFlg" : false,
"dataType" : "Percent",
"defaultTypeFlg" : true,
"defaultValue" : "Unlimited",
"description" : null,
"maxValue" : null,
"minValue" : null,
"name" : "LIST",
"benefit" : {
"category" : "Facility Services",
"name" : "Single Limit",
"networkStatus" : "IN_NETWORK",
"planType" : "MedicalPlan",
"sortOrder" : 20,
"subcategory" : "Acupuncture Treatment",
"subcategorySortOrder" : 6
}
}
}]};
// With filter/map
const result = json.benefitValues
.filter(val => val.amountType.benefit.subcategory === "Acupuncture Treatment")
.map(val => ({Subcategory: val.amountType.benefit.subcategory, Value: val.value, Type: val.amountType.dataType}));
console.log(result)
// With find / manual transform:
const singleFullResult = json.benefitValues
.find(val => val.amountType.benefit.subcategory === "Acupuncture Treatment")
const singleResult = {
Subcategory: singleFullResult.amountType.benefit.subcategory,
Value: singleFullResult.value,
Type: singleFullResult.amountType.dataType
}
console.log(singleResult)
You can use Array.prototype.filter() combined with Array.prototype.map() and create an array of object with the structure you need. Here's an example:
let myArray = [{
"changeDate": "2017-10-13T20:26:13.000+0000",
"changeUserName": "aaaa",
"numericValue": 20,
"value": "20",
"amountType": {
"allowCustomDataFlg": false,
"dataType": "Percent",
"defaultTypeFlg": true,
"defaultValue": "Unlimited",
"description": null,
"maxValue": null,
"minValue": null,
"name": "LIST",
"benefit": {
"category": "Facility Services",
"name": "Single Limit",
"networkStatus": "IN_NETWORK",
"planType": "MedicalPlan",
"sortOrder": 20,
"subcategory": "Acupuncture Treatment",
"subcategorySortOrder": 6
}
}
}];
let ret = myArray
.filter(arr => arr.amountType.benefit.subcategory === 'Acupuncture Treatment')
.map(arr => {
return {
Subcategory: arr.amountType.benefit.subcategory,
Value: arr.value,
Type: arr.amountType.dataType
};
});
console.log(ret);
First the filter function will filter your array and return only the items related to 'Acupuncture Treatment', then the map function, that receives as a parameter a function that will be executed for each item inside the array and it will return a new structure, will return only the fields you need.

How to move nested object into top level without removing top level?

suppose i have this data:
data = [{
"_id" : "2fApaxgiPx38kpDLA",
"profile" : {
"name" : "Karina 1",
"avatar" : "avatar1.jpg",
"bio" : "my bio 1"
},
{
"_id" : "NXM6H4EWfeRAAhB7c",
"profile" : {
"name" : "Karina 2",
"avatar" : "avatar2.jpg",
"bio" : "my bio 2"
},
}];
i did _.map(data, "profile") but it remove top level _id:
wrongResult = [{
"name" : "Karina 1",
"avatar" : "avatar1.jpg",
"bio" : "my bio 1"
},
{
"name" : "Karina 2",
"avatar" : "avatar2.jpg",
"bio" : "my bio 2"
}];
How to move nested object into top level without removing top level like this one:
expectedResult = [{
"_id" : "2fApaxgiPx38kpDLA",
"name" : "Karina 1",
"avatar" : "avatar1.jpg",
"bio" : "my bio 1"
},
{
"_id" : "NXM6H4EWfeRAAhB7c",
"name" : "Karina 2",
"avatar" : "avatar2.jpg",
"bio" : "my bio 2"
}];
thank You so much....
Something Like this? (not tested)
_.map(data,function(d){
d.profile._id = d._id;
return d.profile;
});
Recently needed to do something like this myself. Ended up writing a general purpose function to bring all (nested included) object values to the top level:
const reduceObjValues = (obj, cache = {}) => {
const objectValues = Object.keys(obj).reduce((acc, cur) => {
if (!Array.isArray(obj[cur]) && typeof obj[cur] === 'object') {
return reduceObjValues({ ...acc, ...obj[cur] }, cache);
}
acc[cur] = obj[cur];
return acc;
}, {});
return {
...objectValues,
...cache,
};
}
reduceObjValues({
a: {
b: 'a',
c: 'b',
},
d: {
e: 'a',
f: {
g: {
h: [
1,
2,
3,
]
}
}
}
});
=> { b: 'a', c: 'b', e: 'a', h: [ 1, 2, 3 ] }
one issue with this function is that it will overwrite any keys that are the same.
You can use flatten to move the nested object to its parent level... https://www.npmjs.com/package/flat
Since you are using lodash, I came up with a generic function to flatten out any deeply nested object.
const flattener = obj => {
const toPairs = obj => _.entries(obj).map(([key, val]) => typeof val === 'object' ? toPairs(val) : [key, val]);
return _.chain(toPairs(obj)).flattenDeep().chunk(2).fromPairs().value();
}
So, with an array like this
data = [
{
"_id" : "2fApaxgiPx38kpDLA",
"profile" : {
"name" : "Karina 1",
"avatar" : "avatar1.jpg",
"bio" : "my bio 1"
}
},
{
"_id" : "NXM6H4EWfeRAAhB7c",
"profile" : {
"name" : "Karina 2",
"avatar" : "avatar2.jpg",
"bio" : "my bio 2"
},
}
]
you can do
data.map(obj => flattener(obj))
which will give you
[
{
"_id": "2fApaxgiPx38kpDLA",
"name": "Karina 1",
"avatar": "avatar1.jpg",
"bio": "my bio 1"
},
{
"_id": "NXM6H4EWfeRAAhB7c",
"name": "Karina 2",
"avatar": "avatar2.jpg",
"bio": "my bio 2"
}
]
NB: This flattener function will throw away duplicate object keys, so if you have an object like;
myObj = { name: 'rick', age: 10, country: { name: 'uganda' } }
Flattening this out by calling flattener(myObj) will result in
{ name: 'uganda', age: 10 }
and not in
{ name: 'uganda', age: 10, name: 'rick' }
because you can't have an object with 2 similar keys even if the values to those keys are unique.

Categories

Resources