How to get filtered the array in json reponse based on condition check with keys in angular 7 - json

I would like to get filterd the particular array alone from the json response when dataID is not matched with the ParentDataID from another array in same json response using typescript feature in Angular 7
{ "data":[
{
"dataId":"Atlanta",
"parentDataId":"America"
},
{
"dataId":"Newyork",
"parentDataId":"America"
},
{
"dataId":"Georgia",
"parentDataId":"Atlanta"
},
{
"dataId":"South",
"parentDataId":"Atlanta"
},
{
"dataId":"North",
"parentDataId":"South"
}
]
}
In above response the value of dataId Newyork is not matched with any of the parentDataId entire array json response. So Now i want to filtered out only the second array of DataID alone to make new array.
I would like to have this validation in Typescript angular 7
My output is supposed to like below... The DataId does not have the parentDataId
[
{
"dataId":"Newyork",
"parentDataId":"America"
},
{
"dataId":"Georgia",
"parentDataId":"Atlanta"
},
{
"dataId":"North",
"parentDataId":"South"
}
]
Appreciate the help and response

You can use filter method:
let filterKey = 'Atlanta';
const result = data.data.filter(f=> f.parentDataId != filterKey
&& f.dataId != filterKey);
An example:
let data = { "data":[
{
"dataId":"Atlanta",
"parentDataId":"America"
},
{
"dataId":"Newyork",
"parentDataId":"America"
},
{
"dataId":"Georgia",
"parentDataId":"Atlanta"
}
]
};
let filterKey = 'Atlanta';
const result = data.data.filter(f=> f.parentDataId != filterKey
&& f.dataId != filterKey);
console.log(result);

demo in this StackBlitz Link
my solution is like below code snippet. ts
reducedData = [...this.data];
this.data.reduce((c,n,i) => {
this.data.reduce((d,o, inex) => {
if ( n.dataId === o.parentDataId){
this.reducedData.splice(i,1, {'dataId': 'removed', parentDataId: 'true'});
} else {
return o;
}
},{});
return n;
}, {});
this.reducedData = this.reducedData.filter (value => value.dataId !== 'removed');
html file
<h4> dataId does not have parentId </h4>
<hr>
<pre>
{{reducedData | json}}
</pre>
EDIT
If you do not want to use second object reducedData, then below solution is fine to work.. StackBlitz Link
component.ts
this.data.reduce((c,n,i) => {
this.data.reduce((d,o, inex) => {
if ( n.dataId === o.parentDataId) {
this.data[i]['removed'] = "removed";
} else{
return o;
}
},{});
return n;
}, {});
this.data = this.data.filter (value => value['removed'] !== 'removed');
component.html
<h4> dataId does not have parentId </h4>
<hr>
<pre>
{{data |json}}
</pre>

Please try like this.
const data = { "data":[
{
"dataId":"Atlanta",
"parentDataId":"America"
},
{
"dataId":"Newyork",
"parentDataId":"America"
},
{
"dataId":"Georgia",
"parentDataId":"Atlanta"
}
]
};
const filterKey = "Newyork"
const matchExist = data.data.some( item => item.parentDataId === filterKey && item.dataId === filterKey)
let filteredArray ;
if(!matchExist){
filteredArray = data.data.find(item => item.dataId === filterKey )
}

Related

Console.log json specific value

I'm working with some script and I would like to ask how to display on the console a specific json value.
For example, I have script:
Promise.all([
fetch('https://blockchain.info/balance?active=3C6WPNa5zNQjYi2RfRmt9WUVux7V4xbDmo').then(resp => resp.json()),
fetch('https://api.binance.com/api/v3/avgPrice?symbol=BTCEUR').then(resp => resp.json()),
]).then(console.log)
output:
[{
3C6WPNa5zNQjYi2RfRmt9WUVux7V4xbDmo: {
final_balance: 185653,
n_tx: 1,
total_received: 185653
}
}, {
mins: 5,
price: "19230.49330261"
}]
I want to console price and final_balance.
Best regards!
One way you could achieve this is by flattening the array and objects within because there's no predefined structure of what the output looks like.
Here, I'm assuming the output you mentioned is always an array of objects.
const flattenObject = (obj = {}) =>
Object.keys(obj || {}).reduce((acc, cur) => {
if (typeof obj[cur] === "object") {
acc = { ...acc, ...flattenObject(obj[cur]) };
} else {
acc[cur] = obj[cur];
}
return acc;
}, {});
const outputs = [
{
"3C6WPNa5zNQjYi2RfRmt9WUVux7V4xbDmo": {
final_balance: 185653,
n_tx: 1,
total_received: 185653,
},
},
{
mins: 5,
price: "19230.49330261",
},
];
outputs.forEach((output) => {
const flatOutput = flattenObject(output);
console.log("flatOutput:", flatOutput);
if (flatOutput.final_balance) {
console.log("final_balance:", flatOutput.final_balance);
}
if (flatOutput.price) {
console.log("price:", flatOutput.price);
}
});

JSON data calculation and re-formate using Angular

I have a JSON file and I am trying to calculate the JSON file key based on the value and reformating it. My JSON file looks like below:
data=[
{
pet:'Cat',
fruit:'Apple',
fish:'Hilsha'
},
{
pet:'Dog',
fish:'Carp'
},
{
pet:'Cat',
fruit:'Orange',
fish:'Lobster'
}
];
I do like to calculate and formate it like below:
data=[
{
label:'Pet',
total:3,
list:[
{
name:'Cat',
value: 2,
},
{
name:'Dog',
value: 1,
}
]
},
{
label:'Fruit',
total:2,
list:[
{
name:'Apple',
value: 1,
},
{
name:'Orange',
value: 1,
}
]
},
{
label:'Fish',
total:3,
list:[
{
name:'Hilsha',
value: 1,
},
{
name:'Carp',
value: 1,
},
{
name:'Lobster',
value: 1,
}
]
},
];
If anybody can help me, it will be very help for me and will save a day.
I have fixed this task myself. If I have any wrong, you can put your comment fill-free :)
``
ngOnInit(): void {
this.dataService.$data.subscribe(data => {
// Create new object and calculation according to category
let petObj: any = {}
let fruitObj: any = {}
let fishObj: any = {}
data.forEach((el: any) => {
if (el.pet != undefined) {
petObj[el.pet] = (petObj[el.pet] || 0) + 1;
}
if (el.fruit != undefined) {
fruitObj[el.fruit] = (fruitObj[el.fruit] || 0) + 1;
}
if (el.fish != undefined) {
fishObj[el.fish] = (fishObj[el.fish] || 0) + 1;
}
});
// Create list according to category
let pet_list: any = [];
let fruit_list: any = [];
let fish_list: any = [];
for (var key in petObj) {
let pet = {
label: key,
value: petObj[key]
}
pet_list.push(pet)
}
for (var key in fruitObj) {
let fruit = {
label: key,
value: fruitObj[key]
}
fruit_list.push(fruit)
}
for (var key in fishObj) {
let fish = {
label: key,
value: fishObj[key]
}
fish_list.push(fish)
}
// Calculate total sum according to category
var totalPet = pet_list.map((res: any) => res.value).reduce((a: any, b: any) => a + b);
var totalFruit = fruit_list.map((res: any) => res.value).reduce((a: any, b: any) => a + b);
var totalFish = fish_list.map((res: any) => res.value).reduce((a: any, b: any) => a + b);
// Rearrange the JSON
this.rearrangeData = [
{
label: 'Pet',
total: totalPet,
list: pet_list
},
{
label: 'Fruit',
total: totalFruit,
list: fruit_list
},
{
label: 'Fish',
total: totalFish,
list: fish_list
}
]
console.log(this.rearrangeData)
// End rearrange the JSON
});
}
``
You can simplify your function. Take a look this one
group(oldData) {
const data = []; //declare an empty array
oldData.forEach((x) => {
//x will be {pet: 'Cat',fruit: 'Apple',fish: 'Hilsha'},
// {pet: 'Dog',fish: 'Carp'}
// ...
Object.keys(x).forEach((key) => {
//key will be 'pet','fruit',...
const item = data.find((d) => d.label == key); //search in the "data array"
if (item) { //if find it
item.total++; //add 1 to the property total of the element find it
// and search in the item.list the 'Cat'
const list = item.list.find((l) => l.name == x[key]);
//if find it add 1 to the property value of the list
if (list)
list.value++;
else
//if not, add to the list
//an object with property "name" and "value" equal 1
item.list.push({ name: x[key], value: 1 });
} else
//if the element is not in the "array data"
//add an object with properties label, total and list
//see that list is an array with an unique element
data.push({
label: key,
total: 1,
list: [{ name: x[key], value: 1 }],
});
});
});
return data;
}
You can use like
this.dataService.$data.subscribe(data => {
this.rearrangeData=this.group(data)
}
NOTE: this function the labels are 'pet','fruit' and 'fish' not 'Pet', 'Fruit' and 'Fish'
Did you try reading the text leading up to this exercise? That'd be my first approach. After that, I'd use reduce. You can do pretty much anything with reduce.

Unable to access inner JSON value in JSON array - Typescript(Using Angular 8)

I am trying to use the group by function on a JSON array using the inner JSON value as a key as shown below. But unable to read the inner JSON value. Here is my JSON array.
NotificationData = [
{
"eventId":"90989",
"eventTime":"2019-12-11T11:20:53+04:00",
"eventType":"yyyy",
"event":{
"ServiceOrder":{
"externalId":"2434",
"priority":"1"
}
}
},
{
"eventId":"6576",
"eventTime":"2019-12-11T11:20:53+04:00",
"eventType":"yyyy",
"event":{
"ServiceOrder":{
"externalId":"78657",
"priority":"1"
}
}
}
]
GroupBy Logic:
const groupBy = (array, key) => {
return array.reduce((result, currentValue) => {
(result[currentValue[key]] = result[currentValue[key]] || []).push(
currentValue
);
return result;
}, {});
};
const serviceOrdersGroupedByExternalId = groupBy(this.NotificationData, 'event.ServiceOrder.externalId');
//this line of code is not working as
// it is unable to locate the external id value.
Desired output
{ "2434":[{
"eventId":"90989",
"eventTime":"2019-12-11T11:20:53+04:00",
"eventType":"yyyy",
"event":{
"ServiceOrder":{ "priority":"1" }
}
}],
"78657":[{
"eventId":"6576",
"eventTime":"2019-12-11T11:20:53+04:00",
"eventType":"yyyy",
"event":{
"ServiceOrder":{ "priority":"1" }
}
}]
}
Does this solves your purpose?
let group = NotificationData.reduce((r, a) => {
let d = r[a.event.ServiceOrder.externalId] = [...r[a.event.ServiceOrder.externalId] || [], a];
return r;
}, {});
console.log(group);
Try like this:
result = {};
constructor() {
let externalIds = this.NotificationData.flatMap(item => item.event.ServiceOrder.externalId);
externalIds.forEach(id => {
var eventData = this.NotificationData.filter(
x => x.event.ServiceOrder.externalId == id
).map(function(item) {
delete item.event.ServiceOrder.externalId;
return item;
});
this.result[id] = eventData;
});
}
Working Demo

state district json binding react

I want to display display list of districts from the json, receiving the following error
'TypeError: suggestion.districts.slice(...).toLowerCase is not a function'
json file.
How can I get the list of districts details, so that I can perform autocomplete using downshift?
any help appreciated.
json format
{
"states":[
{
"state":"Andhra Pradesh",
"districts":[
"Anantapur",
"Chittoor",
"East Godavari",
]
},
{
"state":"Arunachal Pradesh",
"districts":[
"Tawang",
"West Kameng",
"East Kameng",
]
},
}
component
import React, { Component } from 'react'
import statedist from "./StateDistrict.json";
const suggestions = statedist.states;
/*.... */
function getSuggestions(value, { showEmpty = false } = {}) {
// const StatesSelected=props.StatesSelected;
const inputValue = deburr(value.trim()).toLowerCase();
const inputLength = inputValue.length;
let count = 0;
//console.log(StatesSelected)
return inputLength === 0 && !showEmpty
? []
: suggestions.filter(suggestion => {
const keep =
count < 5 &&
suggestion.districts.slice(0, inputLength).toLowerCase() === inputValue;
if (keep) {
count += 1;
}
return keep;
});
}
function renderSuggestion(suggestionProps) {
const {
suggestion,
index,
itemProps,
highlightedIndex,
selectedItem
} = suggestionProps;
const isHighlighted = highlightedIndex === index;
const isSelected = (selectedItem || "").indexOf(suggestion.districts) > -1;
return (
<MenuItem
{...itemProps}
key={suggestion.districts[0]}
selected={isHighlighted}
component="div"
style={{
fontWeight: isSelected ? 500 : 400
}}
>
{suggestion.districts[0]} -- how can I get all the values instead of one here
</MenuItem>
);
}
class autoCompleteState extends Component {
constructor(props) {
super(props);
this.state = {
SelectedState:'',
}
// this.showProfile = this.showProfile.bind(this)
}
setSelectedDistrict = (newState) => {
this.setState({ SelectedState: newState });
console.log(newState)
this.props.onDistrictSelected(newState);
}
render() {
const { classes, } = this.props;
console.log(this.state.SelectedState)
const StatesSelected=this.props.StateList;
return (
<div>
<DownshiftMultiple
classes={classes}
setSelectedDistrict={this.setSelectedDistrict}
StatesSelected={StatesSelected}
/>
</div>
)
}
}
export default withStyles(Styles)(autoCompleteState);
I want the district details to come as suggestion like state in the below image
Currently, you are doing this:
suggestion.districts.slice(0, inputLength).toLowerCase() === inputValue;
This is throwing an error because .slice is copying inputLength items from your districts array and then trying to call .toLowerCase() on that array.
If I understand correctly, you are trying to filter your districts according to the inputValue. One way of doing this would be to use reduce on the districts array like this:
suggestion.districts.reduce((acc,curr)=>curr.substring(0,inputLength)===inputValue?[...acc,curr.substring(0,inputLength)]:acc, [])
If you only want the first 5 then you can slice the result of this:
suggestion.districts.reduce((acc,curr,index)=>index<5&&curr.substring(0,inputLength)===inputValue?[...acc,curr.substring(0,inputLength)]:acc, [])

Update JSON variable based on Mongoose results

I have a JSON variable outside of mongoDB collection as below
var outputJson = [
{
'Product' : 'TV',
'isSelected': 0
},
{
'Product' : 'Radio',
'isSelected': 0
},
{
'Product' : 'Book',
'isSelected': 0
},
{
'Product' : 'Watch',
'isSelected': 0
}
]
Now I want to update the isSelected key if the product exits in MongoDB; I want something like below
var outputJson = [
{
'Product' : 'TV',
'isSelected': 0
},
{
'Product' : 'Radio',
'isSelected': 1
},
{
'Product' : 'Book',
'isSelected': 0
},
{
'Product' : 'Watch',
'isSelected': 1
}
]
Here is the code that I am trying, but I am not getting the above result
outputJson.forEach(function(key,value){
wishlistData.find({userID:req.user.id}, function(err,data{
data.forEach(function(k,i){
if (data[i].product=== outputJson[value].Product){
outputJson[value].isSelected = 1
}
})
});
})
Any help is appreciated
Firstly, the callback function to forEach is called with the item in the array as the first argument, so data[i] and outputJson[value] are redundant.
You should make use of mongoose's findOne method to see if there's at least one match, and you can pass in Product as follows
outputJson.forEach(function(item) {
wishlistData.findOne({userID: req.user.id, product: item.Product}, function(err, data) {
if (data !== null) { // if it actually found a match
item.isSelected = 1;
}
});
});
But keep in mind that mongoDB queries are asynchronous, so outputJson would still be the same right after the forEach loop. You might want to use promises and Promise.all to ensure that you do stuff with outputJson after all the queries have been processed:
Promise.all(outputJson.map(function(item) {
return wishlistData.findOne({userID: req.user.id, product: item.Product}).then(function(err, data) {
if (data !== null) { // if it actually found a match
item.isSelected = 1;
}
});
})).then(function() {
// do stuff with outputJson here
});
Replace this
if (data[i].product=== outputJson[value].Product){
outputJson[value].isSelected = 1
}
by
if (data[k].product=== outputJson[key].Product){
outputJson[key].isSelected = 1
}
each callback function have first argument as index
First thing, why are you doing the same mongo query repeatedly for each object in the Array, as it will give you the same result. Also use the lodash library 'lodash'. This is how you can achieve this:
var _ = require('lodash')
wishlistData.find({userID:req.user.id}, function (err, data) {
var dataMap = _.indexBy(data, "product");
outputJson.forEach(function(key,value){
if(!_.isEmpty(_.get(dataMap, key.Product))) {
key.isSelected = 1;
}
})
}
Thank you #Ambyjkl, you guidence worked Promise made the trick, I made minor changes to your script and it started working
Promise.all(outputJson.map(function(i,k) {
return wishlistData.findOne({userID: req.user.id, product: i.Product}).then(function(data, err) {
if (data !== null) { // if it actually found a match
i.isSelected = 1;
}
});
})).then(function() {
console.log(outputJson);
});