how to receive inner property string - javascript

I want to receive the dependency string from the dataDependencyMap.
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<script>
var data =
[
{
"id": 1,
"active": true,
"dependency": [
{"id": 2, "type": "critical" },
{"id": 3, "type": "moderate"}
]
},
{
"id": 2,
"active": true,
"dependency":[
{"id": 3, "type": "moderate"}
]
},
{
"id": 3,
"active": false,
"dependency":[]
}
]
// this works as it should
var dataActiveMap = new Map(data.map(obj => [obj.id, obj.active]))
data.forEach(function({id}) {
if (dataActiveMap.get(id) == true ) {
console.log(id, "active: ", true)
}
})
// HERE IS THE PROBLEM: How can I return the dependency string, like "critical" or "moderate"
var dataDependencyMap = new Map(data.map(obj => [obj.id, obj.dependency]))
data.forEach(function({id}) {
if (dataActiveMap.get(id) == true) {
console.log(id, "dependency: ", dependency.value)
}
})
</script>
</html>

There is no value property of dependency, you can pass dependency so that you can access that object like the following way:
<script>
var data =
[
{
"id": 1,
"active": true,
"dependency": [
{"id": 2, "type": "critical" },
{"id": 3, "type": "moderate"}
]
},
{
"id": 2,
"active": true,
"dependency":[
{"id": 3, "type": "moderate"}
]
},
{
"id": 3,
"active": false,
"dependency":[]
}
]
// this works as it should
var dataActiveMap = new Map(data.map(obj => [obj.id, obj.active]))
data.forEach(function({id}) {
if (dataActiveMap.get(id) == true ) {
//console.log(id, "active: ", true)
}
})
// HERE IS THE PROBLEM: How can I return the dependency string, like "critical" or "moderate"
var dataDependencyMap = data.map(({id, dependency}) => ({id, dependency}));
data.forEach(function({id, dependency}) {
if (dataActiveMap.get(id) == true) {
//console.log(id, "dependency: ", dependency);
// if you need the *type* property as comma separated string
console.log("id:", id, "and dependency:", dependency.map(({type}) => type).join(', '));
}
})
</script>

I'm not sure what the dataActiveMap constant would be used for but an alternative solution would be to use for loops. If you still need the dataActiveMap and dataDependencyMap, you can always create those arrays and use the push() method to add the values to the arrays at appropriate times in the loops. Check the solution below.
for (key in data){ // loops through the data array
// console.log(data[key])
if (data[key].active) // checks if each object's active property in data array is true
{
// console.log(data[key].dependency)
for (dependency in data[key].dependency) // loops through dependencies
{
// console.log(data[key].dependency[dependency])
for (props in data[key].dependency[dependency]) // loops through objects nested in dependencies
{
console.log(data[key].dependency[dependency].type) //prints the type property
}
}
}
}

Related

Loop through an array of objects and update parent object count if child object exists

I am using Angular 13 and I have an array of objects like this:
[{
"name": "Operating System",
"checkedCount": 0,
"children": [{
"name": "Linux",
"value": "Redhat",
"checked": true
},
{
"name": "Windows",
"value": "Windows 10"
}
]
},
{
"name": "Software",
"checkedCount": 0,
"children": [{
"name": "Photoshop",
"value": "PS",
"checked": true
},
{
"name": "Dreamweaver",
"value": "DW"
},
{
"name": "Fireworks",
"value": "FW",
"checked": true
}
]
}
]
I would like to loop through the array, check if each object has a children array and it in turn has a checked property which is set to true, then I should update the checkedCount in the parent object. So, result should be like this:
[{
"name": "Operating System",
"checkedCount": 1,
"children": [{
"name": "Linux",
"value": "Redhat",
"checked": true
},
{
"name": "Windows",
"value": "Windows 10"
}
]
},
{
"name": "Software",
"checkedCount": 2,
"children": [{
"name": "Photoshop",
"value": "PS",
"checked": true
},
{
"name": "Dreamweaver",
"value": "DW"
},
{
"name": "Fireworks",
"value": "FW",
"checked": true
}
]
}
]
I tried to do it this way in angular, but this is in-efficient and results in an error saying this.allFilters[i].children[j] may be undefined. So, looking for an efficient manner to do this.
for(let j=0;i<this.allFilters[i].children.length; j++) {
if (Object.keys(this.allFilters[i].children[j]).length > 0) {
if (Object.prototype.hasOwnProperty.call(this.allFilters[i].children[j], 'checked')) {
if(this.allFilters[i].children[j].checked) {
this.allFilters[i].checkedCount++;
}
}
}
}
Use a nested for loop to check all the children. If checked is truthy, increment the count of the parent. You don't need to check if parent.children has any elements since if there are no elements the loop won't run anyways.
// minified data
const data = [{"name":"Operating System","checkedCount":0,"children":[{"name":"Linux","value":"Redhat","checked":!0},{"name":"Windows","value":"Windows 10"}]},{"name":"Software","checkedCount":0,"children":[{"name":"Photoshop","value":"PS","checked":!0},{"name":"Dreamweaver","value":"DW"},{"name":"Fireworks","value":"FW","checked":!0}]}];
for (const parent of data) {
for (const child of parent.children) {
if (child.checked) parent.checkedCount++;
}
}
console.log(data);
No need to complicate it like that, you just need to check checked property in children.
data.forEach((v) => {
v.children.forEach((child) => {
if (child.checked) {
v.checkedCount++;
}
});
});
Using filter + length on children array should do the job:
const data = [{"name":"Operating System","checkedCount":null,"children":[{"name":"Linux","value":"Redhat","checked":true},{"name":"Windows","value":"Windows 10"}]},{"name":"Software","checkedCount":null,"children":[{"name":"Photoshop","value":"PS","checked":true},{"name":"Dreamweaver","value":"DW"},{"name":"Fireworks","value":"FW","checked":true}]}];
data.forEach(itm => {
itm.checkedCount = itm.children?.filter(e => e.checked === true).length ?? 0;
});
console.log(input);
I would suggest going functional.
Using map
const children = arr.map(obj => obj.children);
const result = children.map((child, idx) => {
const checkedCount = child.filter(obj => obj.checked)?.length;
return {
...arr[idx],
checkedCount
};
});
console.log(result)
or using forEach
const result = [];
const children = arr.map(obj => obj.children);
children.forEach((child, idx) => {
const checkedCount = child.filter(obj => obj.checked)?.length;
result[idx] = {
...arr[idx],
checkedCount
};
});
console.log(result)

Find Efficient way of Filtering of two arrays (ArrayA & ArrayB) to make a third ArrayC

Can anyone help me come up with a faster way of filtering the following ArrayC (see below what it should be equal to. ArrayA is self explanatory. ArrayB has inside of each element an object 'data' that has a property "target" as a string "\_teacher" that I can filter out based on a global variable "userType" to distinguish students vs teachers. "filter_klas_1371" ==> filter_{GroepType }_{GroepID} from Array A. This property changes. breaking the string and filtering has giving me a headache, so if there are faster more efficient ways to filter this please let me know.
let userType='teacher'
arrayA: [{
"ID": 1,
"GroepID": 1371,
"GroepType": "klas"
},
{
"ID": 2,
"GroepID": 1372,
"GroepType": "klas"
},
{
"ID": 3,
"GroepID": 1375,
"GroepType": "graad"
}
]
araayB: [{
"id": "bd5b12ba-b433-4610-801e-e0b78fa72ff8",
data: {
"target": "_teacher",
"filter_klas_1371": "true"
}
},
{
"id": "gggfdgdba-gfgg-fff-ggg-7657657676",
data:{
"target": "_teacher_student",
"filter_klas_1375": "true"
}
} {
"id": "uuuykllk-b433-4610-801e-8888888776",
data: {
"target": "_student",
"filter_klas_1372": "true"
}
} {
"id": "jkjkjkklk-jkhjk-66567-666-99977",
data: {
"target": "_teacher_student",
"filter_klas_1372": "true"
}
},
{
"id": "zzzzzzz-b433-4610-801e-8888888776",
data: {
"target": "_teacher",
"filter_klas_1372": "true"
}
},
]
//should get
arrayC:[{
"id": "bd5b12ba-b433-4610-801e-e0b78fa72ff8",
data: {
"target": "_teacher",
"filter_klas_1371": "true"
}
},
{
data: {
"id": "jkjkjkklk-jkhjk-66567-666-99977",
"target": "_teacher_student",
"filter_klas_1372": "true"
}
},
{
"id": "zzzzzzz-b433-4610-801e-8888888776",
data: {
"target": "_teacher",
"filter_klas_1372": "true"
}
}
]
If I understand correct you would like to filter arrayB based on the userType and the values in arrayA. I suggest making an array of all the possible filter_{groepType}_{groepId} with array map:
const filterKeys = arrayA.map(group => `filter_${group.GroepType}_${group.GroepID}`);
Then you can check if one of those values is set as a key in the keys of arrayB, using an intersection of array with a couple of filters. You can do this in more ways:
arrayC = arrayB.filter(item => {
const intersect = Object.keys(item.data).filter(key => filterKeys.includes(key));
return intersect.length > 0; // you can additionally add the filter for target here
})

map whole array if value equal

I would like to map an array where if one of the values equal to a variable then I change the isChecked key for all objects in this array. for e.g.
input array:
[
[
{
"name": "size",
"value": "XS",
"isChecked": false
},
{
"name": "colors",
"value": "black",
"isChecked": false
}
],
[
{
"name": "size",
"value": "XXXL",
"isChecked": false
},
{
"name": "colors",
"value": "brown",
"isChecked": false
}
],
[
{
"name": "size",
"value": "S",
"isChecked": false
},
{
"name": "colors",
"value": "green",
"isChecked": false
}
]
]
input value: black
output:
[
[
{
"name": "size",
"value": "XS",
"isChecked": true
},
{
"name": "colors",
"value": "black",
"isChecked": true
}
],
[
{
"name": "size",
"value": "XXXL",
"isChecked": false
},
{
"name": "colors",
"value": "brown",
"isChecked": false
}
],
[
{
"name": "size",
"value": "S",
"isChecked": false
},
{
"name": "colors",
"value": "green",
"isChecked": false
}
]
]
maybe should i use some callback,promise? How to map this array? I have to somehow return to the value I missed. In this case, if the value in the array is found then all elements in this array should be marked as isChecked = true.
i've got something like this now:
this.allVariants.map((variant, key) => {
return variant.map((opts, k) => {
if (opts.value == val && !opts.isChecked) {
let mapped = variant.map(op => op.isChecked = true);
} else {
let mapped = variant.map(op => op.isChecked = false);
}
return opts
})
})
You could use map method and inside some to check if element exists in sub-array or not.
const data = [[{"name":"size","value":"XS","isChecked":false},{"name":"colors","value":"black","isChecked":false}],[{"name":"size","value":"XXXL","isChecked":false},{"name":"colors","value":"brown","isChecked":false}],[{"name":"size","value":"S","isChecked":false},{"name":"colors","value":"green","isChecked":false}]]
const res = data.map(arr => {
const check = arr.some(({value}) => value == 'black');
return check ? arr.map(e => ({...e, isChecked: true})) : arr
})
console.log(res)
Perhaps you're looking for something like this? As you can see there's a simple map function which will return an array of the relevant values depending on what was input into the function. It will simply map over the provided arrray and update the relevant objects, provided that the find function doesn't return null.
It achieves this by seeing if the provided value can be found within a nested array via using the found function that I've implemented, provided this returns true, it will then use the mutate function. The idea was that you may want to further change different properties on the given object(s) in future, hence why it has a dedicated function.
My answer is similar to #NenadVracar only I broke it up a little more into multiple functions that consume a single line.
let data = [[{name:"size",value:"XS",isChecked:!1},{name:"colors",value:"black",isChecked:!1}],[{name:"size",value:"XXXL",isChecked:!1},{name:"colors",value:"brown",isChecked:!1}],[{name:"size",value:"S",isChecked:!1},{name:"colors",value:"green",isChecked:!1}]];
// A function that states if relevant object with value exists.
let found = v => a => a.some(({value}) => value == v);
// A function used to return data that has been changed, specifically isChecked = true.
let mutate = a => a.map(i => ({...i, isChecked: true}));
// A function to return the desired array, takes an array and a value.
let map = v => a => a.map(o => found(v)(o) ? mutate(o) : o);
console.log(map('black')(data));

cannot update an array of elements via a 2d iteration

I have two arrays of object, the first array (printerChart, around 80 elements) is made of the following type of objects:
[{
printerBrand: 'Mutoh',
printerModel: 'VJ 1204G',
headsBrand: 'Epson',
headType: '',
compatibilty: [
'EDX',
'DT8',
'DT8-Pro',
'ECH',
],
},
....
]
The second array (items, around 500 elements) is made of the following type of objects:
[
{
"customData": {
"brand": {
"value": {
"type": "string",
"content": "hp"
},
"key": "brand"
},
"printer": {
"value": {
"type": "string",
"content": "c4280"
},
"key": "printer"
}
},
"name": "DT8 XLXL",
"image": {
"id": "zLaDHrgbarhFSnXAK",
"url": "https://xxxxxxx.net/images/xxxxxx.jpg"
},
"brandId": "xxxxx",
"companyId": "xxxx",
"createdAt": "2018-03-26T14:39:47.326Z",
"updatedAt": "2018-04-09T14:31:38.169Z",
"points": 60,
"id": "dq2Zezwm4nHr8FhEN"
},
...
]
What I want to do is to iterate via the second array and, if the part of the name of an item (i.e. DT8) is included in an element of the array 'compatibility' of the first array, I would like to include a new properties to it from the element of the first array: printerBrand. I have tried but somehow the iteration doesn't take place correctly. This is what I tried:
items.forEach((item) => {
printerChart.forEach((printer) => {
if (printer.compatibilty.some(compatibleElem => (
item.name.includes(compatibleElem)))) {
item.printerBrand = printer.printerBrand;
} else {
item.printerBrand = '';
}
});
});
What am I doing wrong?
You do
items.items.forEach(...)
Shouldn't you be doing
items.forEach(...)
?
I suggest to initialize item.printerBrand with an empty string and use a nested approach of some for getting a brand and to exit the loops, if found.
This prevents to get an empty string even if there is a brand to assign.
items.forEach((item) => {
item.printerBrand = '';
printerChart.some(printer => {
if (printer.compatibilty.some(compatibleElem => item.name.includes(compatibleElem))) {
item.printerBrand = printer.printerBrand;
return true;
}
});
});

How to append object-key value form one array to other array?

I have an existing array with multiple object. With an interval I would like to update the existing array with values from another array. See the (simplified) example below.
I've serverall gools:
Copy the value of fan_count form the new array, to the current array with the key "fan_count_new"
If a object is removed or added in the New array, it have to do the same to the Current array.
As far I can see now, I can use some es6 functions :) like:
object-assign, but how to set the new key "fan_count_new"?
How to loop through the array to compare and add or remove + copy the fan_count?
Current array:
[{
"fan_count": 1234,
"id": "1234567890",
"picture": {
"data": {
"url": "https://scontent.xx.fbcdn.net/v/photo.png"
}
}
},
{
"fan_count": 4321,
"id": "09876543210",
"picture": {
"data": {
"url": "https://scontent.xx.fbcdn.net/v/photo.png"
}
}
}, ...
]
New array:
[{
"fan_count": 1239,
"picture": {
"data": {
"url": "https://scontent.xx.fbcdn.net/v/photo.png"
}
"id": "1234567890"
},
{
"fan_count": 4329,
"picture": {
"data": {
"url": "https://scontent.xx.fbcdn.net/v/photo.png"
}
},
"id": "09876543210"
}, ...
]]
You can remove elements which doesn't exists in new array by using array.filter and you can loop through the new array to update the same object in the current array:
var currArr = [
{
"fan_count": 1234,
"id": "1234567890",
},
{
"fan_count": 4321,
"id": "09876543210",
},
{
"fan_count": 4321,
"id": "09876543215",
}
];
var newArr = [
{
"fan_count": 1234,
"id": "1234567890"
},
{
"fan_count": 5555,
"id": "09876543210"
}
];
currArr = currArr.filter(obj => newArr.some(el => el.id === obj.id));
newArr.forEach(obj => {
var found = currArr.find(o => o.id === obj.id);
if (found) {
found.fan_count_new = obj.fan_count;
}
});
console.log(currArr);
Later on I realised that is was better to turn it around, add the fan_count form the currArr to the new one. This because it is easier to handle new objects, and you dont't have to deal with deleted objects. So, anybody how is looking for something like this:
newArr.forEach(obj => {
var found = currArr.find(o => o.id === obj.id);
if (found) {
console.log('found: ', found.fan_count, obj.fan_count)
obj.fan_count_prev = found.fan_count;
obj.fan_count_diff = Math.round(obj.fan_count - found.fan_count);
}
if (typeof obj.fan_count_prev === "undefined") {
obj.fan_count_prev = obj.fan_count;
obj.fan_count_diff = 0
}
});

Categories

Resources