serialize array into object in JSON for API - javascript

I am working on Angular 12, in my TS file
I have an array response from a file upload like this-
[
{
"id": "7",
"name": "xyz",
"job": "doctor",
"preference": "1"
},
{
"id": "7",
"name": "xyz",
"job": "nurse",
"preference": "2"
},
{
"id": "7",
"name": "xyz",
"job": "manager",
"preference": "3"
},
{
"id": "7",
"name": "xyz",
"job": "assistant",
"preference": "4"
},
{
"id": "7",
"name": "xyz",
"job": "chairman",
"preference": "5"
},
{
"id": "7",
"name": "xyz",
"job": "designer",
"preference": "6"
}
]
I want to convert this array to an object in JSON like this-
[
{
"id": "7",
"name": "xyz",
"array1": [
{
"date": "today's Date,",
"endDate": "somedate",
"lastUpdatedBy": "someuser",
"array2": [
{
"job": "doctor",
"preference": "1"
},
{
"job": "nurse",
"preference": "2"
},
{
"job": "manager",
"preference": "3"
},
{
"job": "assistant",
"preference": "4"
},
{
"job": "chairman",
"preference": "5"
},
{
"job": "designer",
"preference": "6"
}
]
}
]
}
]
So based on the id and name combination I want to create the object in JSON which will be passed to an API, I've been trying many things by using map or arrays inside array but having a hard time to succeed. Any help would be appreciated.
In map it will not take duplicate keys for same id & name combination. I have tried to create a customized object and loop through it but each time I get a separate result.
After looping through the array I am trying to build an object like this, but it doesn't produce expected result.
my code-
let object = {
id: data[i].id,
name: data[i].name,
array1:[
{
date: dateParam,
endDate: '',
lastUpdatedBy: 'me',
array2: [
{
job: data[i].job,
preference: data[i].preference
}
]
}
]
};

I'd separate this in two steps:
Group the items using id + name as the key
Transform the grouped structure to the desired output
Click here for a working sandbox
Below is the code:
function groupBy<T, TKey>(list: T[], keyGetter: (arg: T) => TKey) {
const map = new Map<TKey, T[]>();
list.forEach((item) => {
const key = keyGetter(item);
const collection = map.get(key);
if (!collection) {
map.set(key, [item]);
} else {
collection.push(item);
}
});
return map;
}
const groupedInput = groupBy(input, (x) => x.id + x.name);
const output = Array.from(groupedInput.entries()).map(([key, value]) => ({
id: value[0].id,
name: value[0].name,
array1: value.map((x) => ({ job: x.job, preference: x.preference }))
}));
console.log(output);
Using input with the data you gave:
const input = [
{
id: "7",
name: "xyz",
job: "doctor",
preference: "1"
},
{
id: "7",
name: "xyz",
job: "nurse",
preference: "2"
},
{
id: "7",
name: "xyz",
job: "manager",
preference: "3"
},
{
id: "7",
name: "xyz",
job: "assistant",
preference: "4"
},
{
id: "7",
name: "xyz",
job: "chairman",
preference: "5"
},
{
id: "7",
name: "xyz",
job: "designer",
preference: "6"
}
];
This will output:
[{
"id": "7",
"name": "xyz",
"array1": [{
"job": "doctor",
"preference": "1"
}, {
"job": "nurse",
"preference": "2"
}, {
"job": "manager",
"preference": "3"
}, {
"job": "assistant",
"preference": "4"
}, {
"job": "chairman",
"preference": "5"
}, {
"job": "designer",
"preference": "6"
}
]
}
]

Related

How to check if value is in an array with objects based on another array

In javascript I'm trying to check if value myPointID from b is in a.
I've tried:
console.log(a.points.filter((f) => f.myPoint.myPointID === b.myPointID));
I can't seem to figure out the correct way.
var a = [
{
"id": "1",
"name": "sample1",
"points": [
{
"pointID": "12",
"name": "sample point",
"myPoint": {
"myPointID": "12345",
"name": "sample my point",
"form": "form1"
}
}
]
},
{
"id": "2",
"name": "sample2",
"points": [
{
"pointID": "123",
"name": "sample point2",
"myPoint": {
"myPointID": "123456",
"name": "sample my point2",
"form": "form2"
}
}
]
},
{
"id": "3",
"name": "sample3",
"points": [
{
"pointID": "123",
"name": "sample point2",
"myPoint": {
"myPointID": "123456",
"name": "sample my point2",
"form": "form2"
}
}
]
}
];
var b = [
{myPointID: "123456", desc: "sm"},
{myPointID: "123456", desc: "sm2"}
];
You could take the wanted id from the filter array and check the data with a nested loop.
const
data = [{ id: "1", name: "sample1", points: [{ pointID: "12", name: "sample point", myPoint: { myPointID: "12345", name: "sample my point", form: "form1" } }] }, { id: "2", name: "sample2", points: [{ pointID: "123", name: "sample point2", myPoint: { myPointID: "123456", name: "sample my point2", form: "form2" } }] }, { id: "3", name: "sample3", points: [{ pointID: "123", name: "sample point2", myPoint: { myPointID: "123456", name: "sample my point2", form: "form2" } }] }],
filter = [{ myPointID: "123456", desc: "sm" }, { myPointID: "123456", desc: "sm2" }],
ids = new Set(filter.map(({ myPointID }) => myPointID));
console.log(data.filter(({ points }) =>
points.some(({ myPoint: { myPointID } }) => ids.has(myPointID))
));
.as-console-wrapper { max-height: 100% !important; top: 0; }
This returns true or false for whether any myPointID from b exists in a using Array.prototype.reduce()
let b_myPointIds = b.map(function(x){ return x.myPointID})
let reducer = function(accumulator, aChild){ // 'value' is an array item from a
if (accumulator) { // if prev iteration returned true then shortcircuit
return accumulator;
}
for(let i = 0; i<aChild.points.length; ++i){
if(b_myPointIds.includes(aChild.points[i].myPoint.myPointID)){
return true;
}
}
return false;
}
let isMyPointIdInA = a.reduce(reducer, false); // false is initial value of 'isMyPointIdInA'
console.log(isMyPointIdInA);
var a = [
{
"id": "1",
"name": "sample1",
"points": [
{
"pointID": "12",
"name": "sample point",
"myPoint": {
"myPointID": "12345",
"name": "sample my point",
"form": "form1"
}
}
]
},
{
"id": "2",
"name": "sample2",
"points": [
{
"pointID": "123",
"name": "sample point2",
"myPoint": {
"myPointID": "123456",
"name": "sample my point2",
"form": "form2"
}
}
]
},
{
"id": "3",
"name": "sample3",
"points": [
{
"pointID": "123",
"name": "sample point2",
"myPoint": {
"myPointID": "123456",
"name": "sample my point2",
"form": "form2"
}
}
]
}
];
var b = [
{myPointID: "123456", desc: "sm"},
{myPointID: "123456", desc: "sm2"}
];
//--------------------------------------------------------------------------
let b_myPointIds = b.map(function(x){ return x.myPointID})
let reducer = function(accumulator, aChild){ // 'value' is an array item from a
if (accumulator) { // if prev iteration returned true then shortcircuit
return accumulator;
}
for(let i = 0; i<aChild.points.length; ++i){
if(b_myPointIds.includes(aChild.points[i].myPoint.myPointID)){
return true; // set accumulator to true
}
}
return false;
}
let isMyPointIdInA = a.reduce(reducer, false); // false is initial value of 'isMyPointIdInA'
console.log(isMyPointIdInA);

Django REST - JSON API results as list by key

I have a very basic API made with Django Rest Framework with an output as follows:
[
{
"name": "John",
"city": "chicago",
"age": "22"
},
{
"name": "Gary",
"city": "florida",
"age": "35"
},
{
"name": "Selena",
"city": "vegas",
"age": "18"
}
]
I want to convert it to the following format to simplify the usage of its data in charts.
{
"name": ["John", "Gary", "Selena"]
"city": ["chicago", "vegas", "florida"]
"age": ["22", "35", "18"]
}
Is there a simple way this can be done in Javascript (and Python just for curiosity)?
2. Can this be proactively solved by adjusting the Serializer or the ViewSet in DRF?
Javascript version:
const data = [
{
name: 'John',
city: 'chicago',
age: '22',
},
{
name: 'Gary',
city: 'florida',
age: '35',
},
{
name: 'Selena',
city: 'vegas',
age: '18',
},
];
const result = Object.keys(data[0]).reduce((obj, key) => {
obj[key] = data.map(_ => _[key]);
return obj;
}, {});
console.log(result);
In Python you could do it like this:
data = [
{
"name": "John",
"city": "chicago",
"age": "22"
},
{
"name": "Gary",
"city": "florida",
"age": "35"
},
{
"name": "Selena",
"city": "vegas",
"age": "18"
}
]
result = {}
for key in data[0]:
result[key] = []
for entry in data:
for key in entry:
result[key].append(entry[key])
print(result)
check this
data = [
{
"name": "John",
"city": "chicago",
"age": "22"
},
{
"name": "Gary",
"city": "florida",
"age": "35"
},
{
"name": "Selena",
"city": "vegas",
"age": "18"
}
]
output = []
name = []
city = []
age = []
for i in data:
name.append(i['name'])
city.append(i['city'])
age.append(i['age'])
output.append({"name":name,"city":city,"age":age})
print(output)

How to traverse data according to an array?

I am trying to traverse the data according to the show array and print the data to see if it is correct. To traverse the list array corresponding to the show array as follows
I want the effect as follows:
[
{
"name": "A",
"age": "10",
},
{
"name": "B",
"age": "20",
}
]
const data = [{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "A",
"age": "10",
"logo": "aa.png",
"note": "aa"
}, {
"name": "B",
"age": "20",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
}]
function init() {
data.map(res => {
if (res.code == 200) {
console.log(res.data.list)
}
})
}
init();
By iterating show (rather than hard-coding name and age), this code would work also if you change the structure of your template:
const data = [{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "A",
"age": "10",
"logo": "aa.png",
"note": "aa"
}, {
"name": "B",
"age": "20",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
}];
var ans = data[0].data.list.map(item => {
var curr = {};
data[0].data.show.forEach(prop => {
curr[prop] = item[prop];
});
return curr;
});
console.log(ans);
You can use reduce in a shorter way:
const data = [
{
code: "200",
msg: "success",
data: {
list: [
{
name: "A",
age: "10",
logo: "aa.png",
note: "aa"
},
{
name: "B",
age: "20",
logo: "bb.png",
note: "bb"
}
],
show: ["name", "age"]
}
}
];
console.log(data[0].data.list.map(x =>
data[0].data.show.reduce((p, c) => ((p[c] = x[c]), p), {})
));
const data = [{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "A",
"age": "10",
"logo": "aa.png",
"note": "aa"
}, {
"name": "B",
"age": "20",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
}];
function init() {
data.map(res => {
if (res.code == 200) {
console.log(res.data.list.map(function(listValue) {
var ret = {};
res.data.show.forEach(function(idx) {
ret[idx] = listValue[idx]
});
return ret;
}));
}
})
}
init();
You can use .map on your data and return false if the code isn't 200, if it is 200, you can return a mapped version of your list array. You can map this array to a subset of each object in your list. The subset is defined by your show array, and so you can use .reduce() on this array to build your mapped object.
See example below:
const data = [{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "A",
"age": "10",
"logo": "aa.png",
"note": "aa"
}, {
"name": "B",
"age": "20",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
}];
function init() {
return data.map(res => {
if (res.code == 200) {
return res.data.list.map((obj) => {
return res.data.show.reduce((acc, prop) => ({...acc, [prop]: obj[prop]}), {});
});
}
return false;
}).filter(Boolean); // filter out any `false` returns
}
console.log(init());
Alternatively, a better approach than mapping your original data would be to use .reduce(). This will create a one-dimensional array of results:
const data = [{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "A",
"age": "10",
"logo": "aa.png",
"note": "aa"
}, {
"name": "B",
"age": "20",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
},
{
"code": "200",
"msg": "success",
"data": {
"list": [{
"name": "C",
"age": "30",
"logo": "aa.png",
"note": "aa"
}, {
"name": "D",
"age": "40",
"logo": "bb.png",
"note": "bb"
}],
"show": [
"name",
"age"
]
}
}];
function init() {
return data.reduce((acc, res) => {
if (res.code == 200) {
return [...acc, ...res.data.list.map((obj) => {
return res.data.show.reduce((acc, prop) => ({...acc, [prop]: obj[prop]}), {});
})];
}
return acc;
}, []);
}
console.log(init());
If you want to show only name and age as
[
{
"name": "A",
"age": "10",
},
{
"name": "B",
"age": "20",
}
]
Array.map can be used
and then you can write your code this way
const data = [
{
code: '200',
msg: 'success',
data: {
list: [
{
name: 'A',
age: '10',
logo: 'aa.png',
note: 'aa'
},
{
name: 'B',
age: '20',
logo: 'bb.png',
note: 'bb'
}
],
show: ['name', 'age']
}
}
]
function init() {
data.map(res => {
if (res.code == 200) {
console.log(
res.data.list.map(item => {
return {
name: item.name,
age: item.age
}
})
)
}
})
}
init()
Does this answer your question?

How to loop through a nested key value pair and filter it based on a array values

I have an array which is built from the user input. I am trying to loop through a nested key value pair and check whether the values in it matches any value of the given array. The purpose is to make a search facility.
My array :
FilteredSelectedOptions=["20180211","Trax","Vienna","AN01020"]
My key value pair is :
trips = {
"20180201": [{
"journeyId": 1001,
"Number": "001",
"DriverName": "Alex",
"Transporter": {
"id": "T1",
"number": "AN01001",
"Company": "Tranzient"
},
"place": [{
"id": 001,
"value": "Washington DC"
},
{
"id": 002,
"value": "Canberra"
}
],
},
{
"journeyId": 1002,
"Number": "001",
"DriverName": "Tom",
"Transporter": {
"id": "T2",
"number": "AN01002",
"Company": "Trax"
},
"place": [{
"id": 2,
"value": "Canberra"
},
{
"id": 4,
"value": "Vienna"
}
],
},
{
"journeyId": 1003,
"Number": "004",
"DriverName": "Jack",
"Transporter": {
"id": "T3",
"number": "AN01003",
"Company": "Trax"
},
"place": [{
"id": 1,
"value": "Washington DC",
}, {
"id": 4,
"value": "Vienna",
}],
}
],
"20180211": [{
"journeyId": 1004,
"Number": "005",
"DriverName": "Jack",
"Transporter": {
"id": "T3",
"number": "AN01013",
"Company": "Trax"
},
"place": [{
"id": 5,
"value": "Bridgetown"
},
{
"id": 6,
"value": "Ottawa"
},
{
"id": 4,
"value": "Vienna"
}
],
},
{
"journeyId": 1005,
"Number": "005",
"DriverName": "Jerry",
"Transporter": {
"id": "T3",
"number": "AN01020",
"Company": "Trax"
},
"place": [{
"id": 5,
"value": "Bridgetown"
},
{
"id": 6,
"value": "Ottawa"
}
],
}
],
"20180301": [{
"journeyId": 1006,
"Number": "005",
"DriverName": "demy",
"Transporter": {
"id": "T3",
"number": "AN01003",
"Company": "Trax"
},
"place": [{
"id": 5,
"value": "Bridgetown"
},
{
"id": 6,
"value": "Ottawa"
}
],
}],
};
I am expecting output like this :
trips = {
"20180201":
[{
"journeyId": 1002,
"Number": "001",
"DriverName":"Tom",
"Transporter": {
"id": "T2",
"number": "AN01002",
"Company": "Trax"
},
"place": [{"id":002,"value":"Canberra" }]
[{"id":004,"value":"Vienna"}]
},
{
"journeyId": 1003,
"Number": "004",
"DriverName":"Jack",
"Transporter": {
"id": "T3",
"number": "AN01003",
"Company": "Trax"
},
"place": [{"id":001,"value":"Washington DC" }]
[{"id":004,"value":"Vienna"}]
}],
"20180211": [{
"journeyId": 1004,
"Number": "005",
"DriverName":"Jack",
"Transporter": {
"id": "T3",
"number": "AN01013",
"Company": "Trax"
},
"place": [{"id":005,"value":"Bridgetown" }]
[{"id":006,"value":"Ottawa"}]
[{"id":004,"value":"Vienna"}]
},
{
"journeyId": 1005,
"Number": "005",
"DriverName": "Jerry",
"Transporter": {
"id": "T3",
"number": "AN01020",
"Company": "Trax"
},
"place": [{
"id": 5,
"value": "Bridgetown"
},
{
"id": 6,
"value": "Ottawa"
}
]
};
I am trying to use a for loop to check each array elements against the key value pair. What I want to do basically is
for (option in FilteredselectedOptions)
{
//logic
}
I have been able to do it for one particular array value:
const filteredTrips = Object.keys(trips).reduce((tmp, x) => {
const filtered = trips[x].filter(y => y.place && y.place.some(z => z.value === 'Vienna'));
if (filtered.length) {
tmp[x] = filtered;
}
return tmp;
}, {});
But how do I do it for all array elements irrespective of how many elements are inside array. Please help in the loop.
Just an approach by trying to filter with finding a single item in the data.
function filter(object, options) {
const check = v => options.includes(v) || v && typeof v === 'object' && Object.keys(v).some(l => check(v[l]));
var result = {};
Object.keys(object).forEach(function (k) {
var temp = options.includes(k)
? object[k]
: object[k].filter(check);
if (temp.length) {
result[k] = temp;
}
});
return result;
}
var trips = { "20180201": [{ journeyId: 1001, Number: "001", DriverName: "Alex", Transporter: { id: "T1", number: "AN01001", Company: "Tranzient" }, place: [{ id: "001", value: "Washington DC" }, { id: "002", value: "Canberra" }] }, { journeyId: 1002, Number: "001", DriverName: "Tom", Transporter: { id: "T2", number: "AN01002", Company: "Trax" }, place: [{ id: 2, value: "Canberra" }, { id: 4, value: "Vienna" }] }, { journeyId: 1003, Number: "004", DriverName: "Jack", Transporter: { id: "T3", number: "AN01003", Company: "Trax" }, place: [{ id: 1, value: "Washington DC" }, { id: 4, value: "Vienna" }] }], "20180211": [{ journeyId: 1004, Number: "005", DriverName: "Jack", Transporter: { id: "T3", number: "AN01013", Company: "Trax" }, place: [{ id: 5, value: "Bridgetown" }, { id: 6, value: "Ottawa" }, { id: 4, value: "Vienna" }] }, { journeyId: 1005, Number: "005", DriverName: "Jerry", Transporter: { id: "T3", number: "AN01020", Company: "Trax" }, place: [{ id: 5, value: "Bridgetown" }, { id: 6, value: "Ottawa" }] }], "20180301": [{ journeyId: 1006, Number: "005", DriverName: "demy", Transporter: { id: "T3", number: "AN01003", Company: "Trax" }, place: [{ id: 5, value: "Bridgetown" }, { id: 6, value: "Ottawa" }] }] },
options = ["20180211", /* "Trax", */ "Vienna", "AN01020"];
console.log(filter(trips, options));
.as-console-wrapper { max-height: 100% !important; top: 0; }
One could use recursion to search for values in an object:
function hasValue(obj, values){
for(const value of Object.values(obj)){
if(typeof value === "object"){
if(hasValue(value, values))
return true;
} else {
if(values.includes(value))
return true;
}
}
return false;
}
Now we could filter your trips by comparing the keys and using the function above:
const filteredTrips = Object.keys(trips).filter(key => {
if(FilteredSelectedOptions.includes(key))
return true;
if(hasValue(trips[key], FilteredSelectedOptions))
return true;
return false;
});
Let me know if you want a complete code.
Lets begin that objects in javascript don't have built in filter or reduce methods, only arrays do. What I would do, I would loop through the object properties, which are arrays, and check if they have one of the properties that are found in the FilteredSelectedOptions. If I find one, I will push it to a new array containing the results.

Javascript count between 2 arrays

I have 2 arrays objects and I need to do a count of home many types of card we have.
The first object contains all the car id's and the second list contains the types of cars.
Here is the data:
var arr = {
"categories": [{
"id": "100",
"name": "category name",
"car_id": "1"
}, {
"id": "192",
"name": "category name here",
"car_id": "25"
}, {
"id": "192",
"name": "category name here",
"car_id": "27"
}]
};
var arr2 = {
"cars": [{
"id": "1",
"name": "car name",
"car_id": "1",
"type": "ford"
}, {
"id": "4",
"name": "name 2",
"car_id": "25",
"type": "ford"
}, {
"id": "4",
"name": "name 2",
"car_id": "27",
"type": "fiat"
}]
};
There's only 5 types of cars so I have 5 variables:
var:
ford,
fiat,
mazda,
mini,
mg
So, what I need to end up with is something like this:
ford: 2;
fiat: 1;
mazda: 0;
mini: 0;
mg: 0;
How can I do this?
If your number of types are fixed, then try this approach
Make an map first
var map = {
ford: 0,
fiat: 0,
mazda: 0,
mini: 0,
mg: 0
};
Now iterate the arrays and count by types
arr2.cars.forEach( function( item ){
map[ item.type ]++;
});
your map is populated with the values now.
var arr2 = {
"cars": [{
"id": "1",
"name": "car name",
"car_id": "1",
"type": "ford"
}, {
"id": "4",
"name": "name 2",
"car_id": "25",
"type": "ford"
}, {
"id": "4",
"name": "name 2",
"car_id": "27",
"type": "fiat"
}]
};
var map = {
ford: 0,
fiat: 0,
mazda: 0,
mini: 0,
mg: 0
};
arr2.cars.forEach(function(item) {
map[item.type] ++;
});
console.log(map);
var arr = {
"categories": [{
"id": "100",
"name": "category name",
"car_id": "1"
}, {
"id": "192",
"name": "category name here",
"car_id": "25"
}, {
"id": "192",
"name": "category name here",
"car_id": "27"
}]
};
var arr2 = {
"cars": [{
"id": "1",
"name": "car name",
"car_id": "1",
"type": "ford"
}, {
"id": "4",
"name": "name 2",
"car_id": "25",
"type": "ford"
}, {
"id": "4",
"name": "name 2",
"car_id": "27",
"type": "fiat"
}]
};
var carCount, typeCount;
arr.categories.forEach(function(item){
if(item.hasOwnProperty("car_id")){
carCount = arr.categories.length;
}
});
arr2.cars.forEach(function(item){
if(item.hasOwnProperty("type")){
typeCount = arr2.cars.length;
}
});
console.log(carCount);
console.log(typeCount);
https://jsfiddle.net/Law7rzc2/
All you need is
countBy(arr2.cars, 'type')
The implementation of countBy is left as an exercise.
Array.prototype.reduce is your go-to for this kind of array computation. A Map will help you keep track of unique car makes as you iterate thru the array of cars.
var obj2 = {
"cars": [{
"id": "1",
"name": "car name",
"car_id": "1",
"type": "ford"
}, {
"id": "4",
"name": "name 2",
"car_id": "25",
"type": "ford"
}, {
"id": "4",
"name": "name 2",
"car_id": "27",
"type": "fiat"
}]
};
const typeStat = cars => {
let map = cars.reduce((m, {type}) =>
m.set(type, (m.get(type) || 0) + 1), new Map());
return Array.from(map, ([make, count]) => ({make, count}));
};
let stats = typeStat(obj2.cars)
console.log(stats);
Output
[
{
"make": "ford",
"count": 2
},
{
"make": "fiat",
"count": 1
}
]

Categories