Filter the JSON - Angular 8 - javascript

{"data": [
{
"client": {
"name": "TEST NAME",
"client_id": "id_client_boU6cpFX55vkLCXt52TSVB"
},
"Pay_list": [
{
"pay_id": "id_pay_aAW6mEvsCpBVT4aASDERTY"
},
{
"pay_id": "id_pay_aAW6mEvsCpBVT4aTDgVCSD"
}
],
"company": {
"name": "ABCD",
"ID": "1234"
}
},
{
"client": {
"name": "TEST NAME",
"client_id": "id_client_boU6cpFX55vkLCXt52TSVB"
},
"Pay_list": [
{
"pay_id": "id_pay_aAW6mEvsCpBVT4aASQQQW"
},
{
"pay_id": "id_pay_aAW6mEvsCpBVT4aTDDFGE"
},
{
"pay_id": "id_pay_aAW6mEvsCpBVT4aTDgVDFE"
}
],
"company": {
"name": "fBfD",
"ID": "5214"
}
},
]
}
JSON
I need to filter this JSON and get the company name.
this.Detail = result.data.filter(item => item.client.client_id== this.client_client_id && item.Pay_list.pay_id == this.PayId);
I have tried the above code and it trow the error because Pay_list is an array.
How can I filter the above JSON? Please assist me.

You can try this snippet instead. Have attached a Stackblitz Demo for your reference :
Possible variables needed for filter:
const clientId = "id_client_boU6cpFX55vkLCXt52TSVB";
const payId = "id_pay_aAW6mEvsCpBVT4aASDERTY";
Code
const result = response
.data
.filter(({ client: { client_id }, Pay_list }) => client_id === clientId && Pay_list.some(pay => pay.pay_id === payId))[0]
.company
.name;
Result:
ABCD

Here you go:
const client_id = 'id_client_boU6cpFX55vkLCXt52TSVB';
const pay_id = 'id_pay_aAW6mEvsCpBVT4aASQQQW';
const filtered = result.data.filter((item) => {
if (item.client.client_id !== client_id) return false;
if (item.Pay_list.map(({ pay_id }) => pay_id).includes(pay_id)) return false;
return true;
});

try this:
const client_id = 'id_client_boU6cpFX55vkLCXt52TSVB';
const pay_id = 'id_pay_aAW6mEvsCpBVT4aASQQQW';
const result = response
.data
.filter(({ client: { client_id }, Pay_list }) => client_id === clientId && Pay_list.some(pay => pay.pay_id === payId))[0]
.company
.name;

Related

How to change the format of JSON in the front-end in React

I have JSON called by fetch request that looks like this:
[{
"type": "1",
"First": {
"Id": "123456"
}
},
{
"type": "2",
"Second": [{
"Id": "13333"
},
{
"Id": "255555"
},
{
"Id": "37777"
},
{
"Id": "48888"
}
]
}
]
What I did is that I find object with type 1 and add it to object which type 2 and splice my array to just have an object which type 2. Now it looks like this:
[{
"type": "2",
"First": {
"Id": "123456"
},
"Second": [{
"Id": "13333"
},
{
"Id": "255555"
},
{
"Id": "37777"
},
{
"Id": "48888"
}
]
}]
I have two problems. First I want to add obeject type 1 to every objects of array second, like this:
[{
"type": "2",
"Second": [{
"Id": "13333",
"First": {
"Id": "123456"
}
},
{
"Id": "255555",
"First": {
"Id": "123456"
}
},
{
"Id": "37777",
"First": {
"Id": "123456"
}
},
{
"Id": "48888",
"First": {
"Id": "123456"
}
}
]
}]
Secondly I want my JSON to just included Second array, like this:
[{
"Id": "13333",
"First": {
"Id": "123456"
}
},
{
"Id": "255555",
"First": {
"Id": "123456"
}
},
{
"Id": "37777",
"First": {
"Id": "123456"
}
},
{
"Id": "48888",
"First": {
"Id": "123456"
}
}
]
How can I solve these two issues? Here is a piece of my code:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
library: null,
perPage: 20,
currentPage: 1,
maxPage: null,
}
}
componentDidMount() {
fetch('/json.bc', {
method: 'get',
})
.then(response => response.text())
.then(text => {
const Maindata = JSON.parse(text.replace(/\'/g, '"'))
const type1 = Maindata.find(({ type }) => type === '1');
const MergedData = Maindata.map(item => item.type === '1' ? item : { ...type1, ...item });
const MergedData2 = MergedData.splice(1)
this.setState(state => ({
...state,
data: MergedData2
}), () => {
this.reorganiseLibrary()
})
}).catch(error => console.error(error))
}
reorganiseLibrary = () => {
const { perPage, data } = this.state;
let library = data;
library = _.chunk(library, perPage);
this.setState({
library,
currentPage: 1,
maxPage: library.length === 0 ? 1 : library.length
})
}
previousPage = event => {
this.setState({
currentPage: this.state.currentPage - 1
})
}
nextPage = event => {
this.setState({
currentPage: this.state.currentPage + 1
})
}
handlePerPage = (evt) =>
this.setState({
perPage: evt.target.value
}, () => this.reorganiseLibrary());
renderLibrary = () => {
const { library, currentPage } = this.state;
if (!library || (library && library.length === 0)) {
return <div>NOResult</div>
}
return library[currentPage - 1].map((item, i) => (
<div className="Wrapper">{item.id}</div>
))
}
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div>
{this.renderLibrary()}
<ul id="page-numbers">
<li>
{currentPage !== 1 && (
<button onClick={this.previousPage}></button>
)}
</li>
<li>{this.state.currentPage}</li>
<li>{this.state.maxPage}</li>
<li>
{(currentPage < maxPage) && (
<button onClick={this.nextPage}></button>
)}
</li>
</ul>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('Result'))
You could get the First from an item with type: 1 using find. Then filter the type: 2 items and create an new array of objects with First nested in every object in Second
const input=[{"type":"1","First":{"Id":"123456"}},{"type":"2","Second":[{"Id":"13333"},{"Id":"255555"},{"Id":"37777"},{"Id":"48888"}]}]
const { First } = input.find(a => a.type === "1") || {}
const output1 = input.filter(a => a.type === "2")
.map(a => {
const Second = a.Second.map(b => ({ ...b, First }))
return { ...a, Second }
})
console.log(JSON.stringify(output1, null, 3))
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can easily get the second output like output1[0].Second. Depends on how many items with type: 2 will be there in the array.

Loop through JSON array of objects and get the properties based on the matching IDs from objects

My target is if the id from digital_assets and products matches then get the value of URL fro digital_assets and ProductName from products object. I'm able to traverse through the object and get the values of digital_assets and products but need some help to compare these two objects based on IDs to get the value of URL and ProductName. Below is what I've done so far.
var data = [{
"digital_assets": [{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}]
}, {
"products": [{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},{
"id": ["BB002", "AA002"],
"ProductName": "PROD 555"
}]
}
];
$.each(data, function () {
var data = this;
//console.log(data);
$.each(data.digital_assets, function () {
var dAssets = this,
id = dAssets['id'];
// console.log(id);
});
$.each(data.products, function () {
var proData = this,
prod_id = proData['id'];
// console.log(prod_id);
$.each(prod_id, function () {
var arr_id = this;
console.log(arr_id);
});
});
});
Do I need to create new arrays and push the values into the new arrays? Then concat() these array to one. ? Bit lost any help will be appreciated.
Here is one way you can do this via Array.reduce, Array.includes, Object.entries and Array.forEach:
var data = [{ "digital_assets": [{ "id": "AA001", "url": "https://via.placeholder.com/150" }, { "id": "AA002", "url": "https://via.placeholder.com/150" } ] }, { "products": [{ "id": ["BB001", "AA001"], "ProductName": "PROD 485" }, { "id": ["BB002", "AA002"], "ProductName": "PROD 555" } ] } ]
const result = data.reduce((r,c) => {
Object.entries(c).forEach(([k,v]) =>
k == 'digital_assets'
? v.forEach(({id, url}) => r[id] = ({ id, url }))
: v.forEach(x => Object.keys(r).forEach(k => x.id.includes(k)
? r[k].ProductName = x.ProductName
: null))
)
return r
}, {})
console.log(Object.values(result))
You can use Array.prototype.find, Array.prototype.includes and Array.prototype.map to achieve this very gracefully.
let data = [
{
"digital_assets": [
{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},
{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}
]
},
{
"products": [
{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},
{
"id": ["BB002","AA002"],
"ProductName": "PROD 555"
}
]
}
];
// Find the 'digital_assets' array
let assets = data.find(d => d['digital_assets'])['digital_assets'];
// Find the 'products' array
let products = data.find(d => d['products'])['products'];
// Return an array of composed asset objects
let details = assets.map(a => {
return {
id : a.id,
url : a.url
name : products.find(p => p.id.includes(a.id)).ProductName
};
});
console.log(details);
changed answer to fit your needs:
var data = [
{
"digital_assets": [
{
"id": "AA001",
"url": "https://via.placeholder.com/150"
},
{
"id": "AA002",
"url": "https://via.placeholder.com/150"
}
]
},
{
"products": [
{
"id": ["BB001", "AA001"],
"ProductName": "PROD 485"
},
{
"id": ["BB002","AA002"],
"ProductName": "PROD 555"
}
]
}
]
let matchingIds = [];
let data_assetsObject = data.find(element => {
return Object.keys(element).includes("digital_assets")
})
let productsObject = data.find(element => {
return Object.keys(element).includes("products")
})
data_assetsObject["digital_assets"].forEach(da => {
productsObject["products"].forEach(product => {
if (product.id.includes(da.id)){
matchingIds.push({
url: da.url,
productName: product.ProductName
})
}
})
})
console.log(matchingIds);
working fiddle: https://jsfiddle.net/z2ak1fvs/3/
Hope that helped. If you dont want to use a new array, you could also store the respective data within the element you are looping through.
Edit:
I think i know why i got downvoted. My example works by making data an object, not an array. changed the snippet to show this more clearly.
Why is data an array anyway? Is there any reason for this or can you just transform it to an object?
Edit nr2:
changed the code to meet the expectations, as i understood them according to your comments. it now uses your data structure and no matter whats in data, you can now search for the objects containing the digital_assets / products property.
cheers
https://jsfiddle.net/2b1zutvx/
using map.
var myobj = data[0].digital_assets.map(function(x) {
return {
id: x.id,
url: x.url,
ProductName: data[1].products.filter(f => f.id.indexOf(x.id) > -1).map(m => m.ProductName)
};
});

How do I complete an array of information with async calls?

I have this code to fill an array with info about all books a person owns:
async getAllInfo(person_id)
{
let book_list = await this.getBooks(person_id);
for(let book in book_list)
{
book_list[book]["book_info"] = await this.getBookInfo(book_list[book]["book_id"])
}
return book_list;
}
When I run the getBooks I get:
[
{
"name": "BookA",
"book_id" : "123"
},
{
"Name": "BookB",
"book_id" : "456"
}
]
And then I complete the info about the book in the for loop:
[
{
"name": "BookA",
"book_id" : "123",
"book_info": {
"author": "authorA",
"publish_year": 1900
}
},
{
"name": "BookB",
"book_id" : "456",
"book_info": {
"author": "authorB",
"publish_year": 1900
}
}
]
The getBooks and getBookInfo are http calls and when a person have lots of books it may take some time to get all the information. Is is possible to get it simultaneously for all books in the array? I tried to remove the await and use the Promise.all(), but I always get:
[
{
"name": "BookA",
"book_id" : "123",
"book_info": {
"domain": {
"domain": null,
"_events": {},
"_eventsCount": 1,
"members": []
}
}
},
{
"name": "BookB",
"book_id" : "456",
"book_info": {
"domain": {
"domain": null,
"_events": {},
"_eventsCount": 1,
"members": []
}
}
}
]
What you're doing in this piece of code can be optimised:
for(let book in book_list) {
book_list[book]["book_info"] = await this.getBookInfo(book_list[book]["book_id"])
}
Because for each book your making a request and waiting for this request to complete before fetching the details of the next book. Here is how you can perform all the requests at once and wait for all the details of the books to be retrieved:
async getAllInfo(person_id) {
let book_list = await this.getBooks(person_id);
// Creating an array of Promises to fetch the details of all the books simultaneously
const fetchingBooksDetails = book_list.map(book => this.getBookInfo(book.book_id));
// Wainting for the requests to complete
const booksDetails = await Promise.all(fetchingBooksDetails);
// Saving the details of the book in the book_list variable
booksDetails.forEach((bookDetails, index) => {
book_list[index].book_info = bookDetails;
});
return book_list;
}
Try something like this (not tested)
async getAllInfo(person_id)
{
let book_list = await this.getBooks(person_id);
for(let book in book_list)
{
book_list[book]["book_info"] = this.getBookInfo(book_list[book]["book_id"])
}
await Promise
.all(book_list[book].map(b => b.book_info))
.then(infos => {
for (book in infos)
book_list[book]["book_info"] = infos[book];
});
return book_list;
}
function getAllInfo(person_id){
return getBooks(person_id).then(function(book_list){
var promiseArray = []
book_list.forEach(function(book,index){
promiseArray.push(getBookInfo(book_list[index]["book_id"]))
})
return Promise.all(promiseArray).then(function(values){
book_list.forEach(function(book,index){
book_list[index]["book_info"] = values[index]
})
return book_list
})
})
}
function getBooks(person_id){
return new Promise(function(resolve,reject){
resolve(
[
{
"name": "BookA",
"book_id" : "123"
},
{
"Name": "BookB",
"book_id" : "456"
}
]
)
})
}
function getBookInfo(book_id){
return new Promise(function(resolve,reject){
if(book_id=="123"){
resolve({
"author": "authorA",
"publish_year": 1900
})
}
else if(book_id=="456"){
resolve({
"author": "authorB",
"publish_year": 1900
})
}
else{
reject()
}
})
}
getAllInfo("rap_mosnter").then(function(data){
console.log(data)
})

recursion with Promises

I have a collection in MongoDB like this
[
{
"classId": "1",
"name": "Input",
"definition": [
{
"property": [
{
"classId": "12",
"name": "One"
},
{
"classId": "8",
"name": "Comment"
}
]
}
]
},
{
"classId": "8",
"name": "CommentDetail",
"definition": [
{
"property": [
{
"classId": "10",
"name": "user"
},
{
"classId": "10",
"name": "message"
}
]
}
]
},
{
"classId": "10",
"name": "String",
"definition": []
},
{
"classId": "12",
"name": "Int",
"definition": []
}
]
Based on db above, I have a model to display
data = {
name:'',
template: ''
}
With classId=1, the expectation result is
{
"Name": "Input",
"temlate": "{['One': 'Int','Comment': ['user': 'String','message':'String']]}"
}
I try to using recursive promise to implement it. When property[] is empty, the result will be return.
Here is my function:
const getObjectTypeByClassId = (snapshotId, artifactId, objectType) => {
return artifactDetailModel.find({
'snapshotId': snapshotId,
'artifactId': artifactId
})
.then(data => {
let artifact = data[0];
let definition;
let definitionData = {};
return Promise.resolve()
.then(() => {
definition = artifact.data.teamworks.twClass[0].definition[0];
if (!lodash.isUndefined(definition.property)) {
const listOfProperty = definition.property;
for (let property of listOfProperty) {
classId = commonUtil.getArtifactId(property.classRef[0]);
if (!lodash.isUndefined(classId)) {
return getObjectTypeByClassId(snapshotId, classId, objectType);
}
}
} else {
definitionData.nameType = artifact.data.teamworks.twClass[0].elementAttribute.name;
definitionData.classId = artifact.data.teamworks.twClass[0].elementAttribute.id;
definitionData.template = bpmMapping.objectType[artifact.data.teamworks.twClass[0].elementAttribute.name];
return objectTypeModel.create(definitionData)
.then(obj => {
const response = {
name: objectType.name,
isArrayOf: objectType.isArrayOf,
nameType: obj.nameType,
template: obj.template,
}
return response;
})
}
})
})
}
Run with my function, the response is
data: {
Name: Input
temlate: user: String,
}
Please advice me.
I tried it to some extent, but wasn't able to get it right. Plus your expected output is not the valid JSON "temlate": {[]} doesn't make sense.
It has nothing to do with Promise. You have to DFS you db array and created expected output. Here is what I have donup tillll now, you can think along those lines. But this is far from the solution.
let mainArray = [
{
"classId": "1",
"name": "Input",
"definition": [
{
"property": [
{
"classId": "12",
"name": "One"
},
{
"classId": "8",
"name": "Comment"
}
]
}
]
},
{
"classId": "8",
"name": "CommentDetail",
"definition": [
{
"property": [
{
"classId": "10",
"name": "user"
},
{
"classId": "10",
"name": "message"
}
]
}
]
},
{
"classId": "10",
"name": "String",
"definition": []
},
{
"classId": "12",
"name": "Int",
"definition": []
}
]
function dfs(root, createdRoot, fn, level) {
fn(root,createdRoot, level);
if(root.definition)/*if definition exists => keep traversing*/
root.definition[0].property.forEach(function (child) {
createdRoot.template = createdRoot.template || [];
let tempObj = {};
let lookupObj = lookupByClassId(child.classId);
tempObj[child.name] = lookupObj.name;
createdRoot.template.push(tempObj);
dfs(child,tempObj, fn, level + 1);
});
else /*if definition doesn't exist, look into the array*/
{
createdRoot.template = lookupByClassId(root.classId);
}
}
function lookupByClassId(classId){
for(let i=0;i<mainArray.length;++i){
let element =mainArray[i]
if(element.classId == classId)
return element;
}
}
let root = lookupByClassId(1);
createdRoot ={};
function func1(root, createdRoot, level) {
createdRoot.name = root.name;
console.log(root.classId);
}
dfs(root, createdRoot, func1, 0);
here is the solution from a guy on the internet. it works well. Thanks, #Cuong Quach
var MongoClient = require('mongodb').MongoClient;
var database = 'testdequy';
var collection = 'classes';
MongoClient.connect("mongodb://localhost:27017/" + database, function (err, db) {
findDetails("1").then((r) => {
console.log("r>>>", r);
})
function findDetails(classId) {
var results = { Name: "", Template: "" };
var template = {};
return new Promise((main_resolve, reject) => {
process(template, "" , classId)
var works = 0;
function process(parent, childKey, objectId) {
return new Promise((resolve, reject) => {
db.collection(collection).find({ classId: objectId })
.toArray((err, docs) => {
if (results.Name == "") {
results.Name = docs[0].name;
}
let objectItem;
if (childKey == "")
objectItem = parent;
else
objectItem = parent[childKey];
console.log("\ndocs", docs[0], objectId, objectItem)
if (docs[0].definition.length == 0 || docs[0].definition[0].property == undefined) {
let name = docs[0].name;
parent[childKey] = name;
console.log("\nNo child", docs[0],parent, objectItem, docs[0].name)
resolve(0);
} else {
docs[0].definition[0].property.forEach((item) => {
works++;
//console.log("item", item)
let id = item.classId;
let name = item.name;
objectItem[name] = {};
process(objectItem, name, id).then((len)=>{
works--;
if(len == 0 && works == 0) main_resolve(template);
})
})
resolve(docs[0].definition[0].property.length)
}
})
})
}
})
}
});

How i can get data from another object?

Plunker
I have two structures - ingredients and recipes
[{
"id":"1",
"name": "Cucumber"
},
..
]
and
[{
"id":"1",
"name": "Salad1",
"recipein":[1, 3, 5]
}, {
...
}
]
and i want to show names of ingredients in each salad by press a button.
I filtered object to get ID of object, then i try to get a array of ingredients
getSalad(param:number) {
this.saladId = this.recipe.filter(rec => {
return rec.id.includes(param);
})
this.getNameOfIngredients(this.saladId)
}
getNameOfIngredients(saladArray:any) {
var ingredientsId = saladArray.map(function(num) {
return num.recipein;
});
i getting array [1,2,4] now i want to show all names of ingredients from this.ingredients with this array of id's.
How can i do this?
Plunker
I made updates in your plunker. I think thats what are you looking for: Plunker
getSalad(param:number) {
this.saladId = this.recipe.filter(rec => +rec.id === param )[0];
if(!this.saladId){
this.currentSalad = "Salad not found";
return;
}
this.currentSalad = this.getNameOfIngredients(this.saladId)
}
getNameOfIngredients(saladArray:any) {
return this.ingredients.filter( ing => {
return saladArray.recipein.indexOf(+ing.id) !== -1;
});
let _ingredients = []
this.ingredients.foreach((ingr)=>{
if(this.ingreIDArry.indexof(ingr.id) > -1){
_ingredients.push(ingr.name)
}
})
return _ingredients
is this what you want?
if you can flatten the array, it would be very straightforward for us to do lookups.
Here is what you could do.
const salads = [{
"id": "1",
"name": "Salad1",
"recipein": [1, 3, 5]
}];
const ingredients = [{
"id": "1",
"name": "Cucumber"
},
{
"id": "2",
"name": "Cucumber2"
},
{
"id": "3",
"name": "Cucumber3"
},
{
"id": "4",
"name": "Cucumber4"
},
{
"id": "5",
"name": "Cucumber5"
}
];
const flattenIngredients = (() => {
const output = {};
ingredients.forEach((ingredient) => {
output[ingredient.id] = ingredient;
});
return output;
})();
const getSalad = (saladId) => {
const filteredSalad = salads.filter((salad) => {
return saladId == salad.id;
});
if (filteredSalad.length > 0) {
const salad = filteredSalad[0];
return salad.recipein.map((receip) => flattenIngredients[receip].name);
}
}
console.log(getSalad(1));

Categories

Resources