Nested for loop through json object array does not work - javascript

I need to build a new array based on json array (Context) bellow. Unfortunately I never reach the outer Loop after passing by first run. Is there any mistake in code? How can I solve this issue?
Thank you for help.
Context:
"rfqBp": [
{
"rfqBpId": 1041650,
"Contact": [
{
"ID": 1000014,
"SelectedContact": true
},
{
"ID": 1002411,
"SelectedContact": true
},
{
"ID": 1016727,
"SelectedContact": true
},
{
"ID": 1017452,
"SelectedContact": true
}
],
},
{
"rfqBpId": 1052326,
"Contact": [
{
"ID": 1016236,
"SelectedContact": true
},
{
"ID": 1019563,
"SelectedContact": true
}
],
},
{
"rfqBpId": 1056632,
"Contact": [
{
"ID": -1,
"SelectedContact": false
}
],
},
{
"rfqBpId": 1056637,
"Contact": [
{
"ID": 1019875,
"SelectedContact": true
}
],
}
],
script:
$scope.SelectedContacts = function() { //function starts by click on checkbox in html
let selectedContactList = [];
let finalList = [];
$scope.Context.Output = [];
for (let i = 0; i <= $scope.Context.rfqBp.length; i++) {
for (let j = 0; j <= $scope.Context.rfqBp[i].Contact.length; j++) {
if ($scope.Context.rfqBp[i].Contact[j].SelectedContact === true) {
selectedContactList = {
"ID": $scope.Context.rfqBp[i].Contact[j].ID
};
finalList.push(selectedContactList);
} else if ($scope.Context.rfqBp[i].Contact[j].SelectedContact !== true) {
continue;
}
$scope.Context.Output = finalList; //Output works but just for rfqBp[1]
};
};
$scope.Context.Output = finalList; //this part never reached
};
Output:
"Output": [
{
"ID": 1000014
},
{
"ID": 1016727
},
{
"ID": 1017452
}
]
I try to get following:
"Output": [
{
"ID": 1000014
},
{
"ID": 1016727
},
{
"ID": 1017452
},
{
"ID": 1016236
},
{
"ID": 1019563
},
{
"ID": 1019875
}
]

You can use Array.prototype.flatMap() combined with Array.prototype.filter(), Array.prototype.map() and Destructuring assignment:
const rfqBp = [{rfqBpId: 1041650,Contact: [{ID: 1000014,SelectedContact: true,},{ID: 1002411,SelectedContact: true,},{ID: 1016727,SelectedContact: true,},{ID: 1017452,SelectedContact: true,},],},{rfqBpId: 1052326,Contact: [{ID: 1016236,SelectedContact: true,},{ID: 1019563,SelectedContact: true,},],},{rfqBpId: 1056632,Contact: [{ID: -1,SelectedContact: false,},],},{rfqBpId: 1056637,Contact: [{ID: 1019875,SelectedContact: true,},],},]
const result = rfqBp
.flatMap(({ Contact }) => Contact
.filter(({ ID }) => ID > 0) // Filter to exclude negative `ID`s
.map(({ ID }) => ({ ID }))
)
console.log(result)

Related

Push elements of

This is, I believe a very simple question for a JS programmer. Given the following array of objects named "categories"
[
{
"id": 1,
"name": "FURNITURE",
},
{
"id": 2,
"name": "AUTOMOTIVE",
},
{
"id": 3,
"name": "UPHOLSTERY",
}
]
I want to push the "name" on the "selectedCategories" array below where "id" === "id"
[
{
"id": 1
},
{
"id": 3
}
]
Below is my attempt to solve this, but ... not working..
for (let i = 0; i < selectedCategories.length; i++) {
for(let y = 0; y < categories.length; y++){
selectedCategories.name = categories[y].name
}
}
I believe this is what you are looking for
selectedCategories = selectedCategories.map(el => {
const searchEl = categories.find(e => e.id === el.id);
if (searchEl)
return { ...el, name: searchEl.name }
return el;
});
const categories = [
{
"id": 1,
"name": "FURNITURE",
},
{
"id": 2,
"name": "AUTOMOTIVE",
},
{
"id": 3,
"name": "UPHOLSTERY",
}
];
var selectedCategories = [
{
"id": 1,
},
{
"id": 3,
}
];
selectedCategories = selectedCategories.map(
selectedCategory => categories.find(category => category.id === selectedCategory.id),
);
console.log(selectedCategories);

How to filtering out the multiple nested object in Javascript object

Javascript
I have a nested array of objects, I'm trying to filter the given array of objects using a property from the third level of its array property value. For example, from the below array I like to filter the entire array using the property ListId: 10
Example
let test = {
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":11,
"name":"string2",
"state":"BY"
},
{
"ListId":12,
"name":"string3",
"state":"BY"
}
]
}
]
},
{
"name":"header2",
"value":[
{
"id":"01",
"list":[
{
"ListId":100,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":111,
"name":"string2",
"state":"BY"
},
{
"ListId":121,
"name":"string3",
"state":"BY"
}
]
}
]
}
]
}
Filtervalue with ListId = 10
Expected output :
{
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
}
]
}
]
}
]
}
How can I use the filter method using javascript to get this expected result?
You can two it in two times :
First, filter the list arrays,
Secondly filter the groups array using the some method
let test= {
"test": true,
"group": [
{
"name": "header",
"value": [
{
"id": "0",
"list": [
{
"ListId": 10,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 11,
"name": "string2",
"state": "BY"
},
{
"ListId": 12,
"name": "string3",
"state": "BY"
}
]
}
]
},
{
"name": "header2",
"value": [
{
"id": "01",
"list": [
{
"ListId": 100,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 111,
"name": "string2",
"state": "BY"
},
{
"ListId": 121,
"name": "string3",
"state": "BY"
}
]
}
]
}
]
}
test.group.forEach(group => {
group.value.forEach(value => {
value.list = value.list.filter(list => list.ListId === 10)
})
})
test.group = test.group.filter(group => group.value.some(value => value.list.length > 0))
console.log(test)
Note : You should use plural names for you arrays, it helps understanding the data. For example lists not list for the array.
let z ={"group1": [
{
"name": "header",
"value": [
{
"id": 0,
"list": [
{
"ListId": 10,
"Name": "string1"
},
{
"ListId": 11,
"Name": "string2"
}
]
}
]
}
]}
// This function was written from understading that 'group1' is not a fixed property, but part of a dynamic list due to the number '1'
const getItemByListId = (list, listId) => {
const listKeys = Object.keys(list);
const selectedListKey = listKeys.find(key => {
const groupItems = list[key];
const selectedItem = groupItems.find(({ value: nestedItems }) => {
const selectedNestedItem = nestedItems.find(({ list }) => {
const selectedList = list.find(({ ListId }) => ListId === listId)
return selectedList;
});
return selectedNestedItem;
});
return selectedItem;
});
if (!selectedListKey) {
return null;
}
return list[selectedListKey];
};
console.log(getItemByListId(z, 10));

Put JSON data inside another object of the same JSON

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"
}
}
}
]
}

Normalize JSON to a custom schema

I have an array of objects with the following format
var arr = [
{
"productId": "123456",
"productName": "Test Product 1",
"description": [
"This is delicious",
"Suitable for vegetarian"
],
"attributes": {
"internalId": "091283"
"category": "Dairy"
},
"order": 1
}
];
And I am trying to map into something like below
[
[{
{
"name": "productId",
"value": "123456"
},
{
"name": "productName",
"value": "Test Product 1"
},
{
"name": "description",
"value": ["This is delicious", "Suitable for vegetarian"]
},
{
"name": "attributes",
"value": {
{
"name": "internalId",
"value": "091283"
},
{
"name": "category",
"value": "Dairy"
}
}
},
{
"name": "order",
"value": 1
}
}]
]
I tried mapping simple properties before going further and now stuck at getting only the last property of each object in the loop.
Suppose I don't know what are the format of incoming data and how can I normalize the JSON object to the format I want?
normalizeJson = (array) => {
for(i = 0; i < array.length; i++){
normalizedJson[i] = {};
Object.keys(array[i]).forEach(key => {
if (array[i][key] && typeof array[i][key] === "object") {
// normalizeJson(obj[key]);
// console.log(key + ' is object');
return;
} else {
o = {};
o["name"] = key;
o["value"] = array[i][key];
normalizedJson[i] = o;
// normalizedJson[i]["name"] = key;
// normalizedJson[i].value = array[i][key];
// console.log(key);
return;
}
});
}
console.log(normalizedJson);
};
Or is there any library I can use in order to achieve this?
Try this
var obj = [
{
productId: "123456",
productName: "Test Product 1",
description: ["This is delicious", "Suitable for vegetarian"],
attributes: {
internalId: "091283",
category: "Dairy",
},
order: 1,
},
];
function normalizeObject(obj) {
var result = [];
if (Array.isArray(obj)) {
for (let i of obj) {
result.push(normalizeObject(i));
}
} else if (typeof obj == "object") {
for (let i of Object.keys(obj)) {
result.push({ name: i, value: normalizeObject(obj[i]) });
}
} else {
return obj;
}
return result;
}
console.log(JSON.stringify(normalizeObject(obj), null, 2));
This looping method called recursion. Which is loop by calling function itself.

Javascript array of arrays that contains obj, take only arrays that contain an obj with a specific key

I have array of arrays that contains obj, I should only take arrays that contain an obj with a specific key.
I tried to use a double filter but it doesn't work.
Can you give me some advice?
let result = [
[
{
"id": 1
},
{
"id": 2
}
],
[
{
"id": 3
},
{
"id": 4
},
{
"id": 5,
"type": {
"id": 1555
}
}
],
[
{
"id": 6,
"type": {
"id": 5456
}
}
]
];
const c = result.filter(array => array.filter(a => a.hasOwnProperty('type') === true));
console.log(c);
Result:
[
[
{
"id": 3
},
{
"id": 4
},
{
"id": 5,
"type": {
"id": 1555
}
}
],
[
{
"id": 6,
"type": {
"id": 5456
}
}
]
]
The filter in your filter function is wrong because you don't want to return a new collection, you want to return a boolean expression. Array.some() helps and checks if any item in that subarray has this property.
let result = [
[{
"id": 1
},
{
"id": 2
}
],
[{
"id": 3
},
{
"id": 4
},
{
"id": 5,
"type": {
"id": 1555
}
}
],
[{
"id": 6,
"type": {
"id": 5456
}
}]
];
const validArrays = result.filter(subArray => subArray.some(item => item.hasOwnProperty('type')));
console.log(validArrays);
You'll have to check whether the length of the return value from the inner array is > 0. Only if the length of the return value from the inner filter is > 0 the outer filter returns true and store it into validArrays.
let result = [[{"id":1},{"id":2}],[{"id":3},{"id":4},{"id":5,"type":{"id":1555}}],[{"id":6,"type":{"id":5456}}]];
const validArrays = result.filter(subarray => subarray.filter(item => item.hasOwnProperty('type') === true).length > 0);
console.log(validArrays);

Categories