map whole array if value equal - javascript

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));

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)

How to compare 2 arrays for same value and save them to 3rd array with true or false flags

I have 2 arrays:
var arr1 = [{name:"Option1"},{"name":"Option2"},{"name":"Option3"},{"name":"Option4"},{"name":"Option5"},{"name":"Option6"},{"name":"Option7"},{"name":"Option8"},{"name":"Option9"},{"name":"Option10"}]
var arr2 = [{"name": "Option 2"},{"name": "Option 4"},{"name": "Option 6"},{"name": "Option 8"},{"name": "Option 10"}]
What I wish to achive is that a 3rd array with all the values from arr1 with additional flag of "marked":true if that value is found in arr2 ELSE "marked": false
I tried a various combination of arry methods such as map(), filter(), forEach() but somehow not able to figure out how to return properly without repeating the values or making duplicate entries.
** What I see is that my inside and outside loop both statements are executed and I somehow miss the return true / false logic and end up repeating my loop the number of time equal to the length of arr2. **
function test() {
var arr1 = [{
name: "Option1"
},
{
"name": "Option2"
},
{
"name": "Option3"
},
{
"name": "Option4"
},
{
"name": "Option5"
},
{
"name": "Option6"
},
{
"name": "Option7"
},
{
"name": "Option8"
},
{
"name": "Option9"
},
{
"name": "Option10"
}
]
var arr2 = [{
"name": "Option2"
},
{
"name": "Option4"
},
{
"name": "Option6"
},
{
"name": "Option8"
},
{
"name": "Option10"
}
]
arr1.forEach((el) => {
arr2.forEach((el2) => {
if (el.name.toString() === el2.name.toString()) {
return console.log("Printing from inside the if loop", el)
}
console.log("Printing from outside the if loop", el)
})
})
}
test()
Start by mapping all the comparison values (name) from arr2 into a Set.
Then map arr1 to create the new array and lookup each name in the arr2 Set
const arr2Names = new Set(arr2.map(e => e.name));
const res = arr1.map(e => ({...e, marked: arr2Names.has(e.name)}));
console.log(res)
<script>
var arr1=[{name:"Option1"},{name:"Option2"},{name:"Option3"},{name:"Option4"},{name:"Option5"},{name:"Option6"},{name:"Option7"},{name:"Option8"},{name:"Option9"},{name:"Option10"}],
arr2=[{name:"Option2"},{name:"Option4"},{name:"Option6"},{name:"Option8"},{name:"Option10"}];
</script>

How to change original array based on other array

Hello I would like to transform original array coming from API and change users color field into "primary" when their id matches. I've tried to run this code, however it retruns empty array
console.log(array.filter((item, i) => {
return item.id === selected[i]
}))
// Original array
[
{
"id": "183",
"fullName": "Simon Aaman",
"color": "secondary"
},
{
"id": "77",
"fullName": "Dennis Bergkamp",
"color": "secondary"
},
{
"id": "80",
"fullName": "Allison Bäcker",
"color": "secondary"
},
]
/array of ids
const selected = [77, 80]
You can change the color using a map over your array and inside that you can just match against your selected ids.
const arr = [
{
"id": "183",
"fullName": "Simon Aaman",
"color": "secondary"
},
{
"id": "77",
"fullName": "Dennis Bergkamp",
"color": "secondary"
},
{
"id": "80",
"fullName": "Allison Bäcker",
"color": "secondary"
},
];
const selected = [77, 80];
const result = arr.map((el) => {
if(selected.includes(Number(el.id))){
return {
...el,
color: 'primary'
}
}
return el;
});
console.log(result);
Also you had a problem with you code, you were strictly checking the ids using === which means you were looking for the type too (one was Number and one was a String), you could have done it using == which does not check for the type or just convert one of the ids to String/Number.
You need to use == or convert the string to Number since === will check datatype as well.
console.log(array.filter((item, i) => {
return +item.id === selected[i]
}))
or
console.log(array.filter((item, i) => {
return item.id == selected[i]
}))
You can try to filter from selected:
console.log(selected.map((s) => {
return array.filter(el=>el.id ===`${s}`)
}))

Javascript -sort array based on another javascript object properties

I have one javascript array and one object . Need help to sort javascript object keys based on the order number in another array
In subgroup array , I have name , order number. Need to sort Offerings keys based on that order number
const subgroup = [
{
"code": "6748",
"name": "test123",
"orderNumber": "0"
},
{
"code": "1234",
"name": "customdata",
"orderNumber": "1"
}
]
const offerings = {
"customdata" : [
{
"code": "Audi",
"color": "black"
}
],
"test123" : [
{
"brand": "Audi",
"color": "black"
}
]
}
I believe this should work for you. I've added some comments in the code that should hopefully do an okay job of explaining what is happening.
var subgroup = [{
"code": "6748",
"name": "test123",
"orderNumber": "0"
}, {
"code": "1234",
"name": "customdata",
"orderNumber": "1"
}];
var offerings = {
"customdata": [{
"code": "Audi",
"color": "black"
}],
"test123": [{
"brand": "Audi",
"color": "black"
}]
}
function sortObjectFromArray(refArray, sortObject, orderKey = 'order', linkKey = 'key') {
// Get copy of refArray
let reference = refArray.slice();
// Sort sortObject [ into an array at this point ]
let sorted = [];
for (let key in sortObject) {
// Searches the refArray for the linkKey, and returns the intended index
let index = reference.find((item) => item[linkKey] === key)[orderKey];
// Places the sortObject's value in the correct index of the 'sorted' Array
sorted[parseInt(index)] = [key, sortObject[key]];
};
// Return an object, created from previous 'sorted' Array
return sorted.reduce((obj, [key, value]) => {
obj[key] = value;
return obj;
}, {});
};
offerings = sortObjectFromArray(subgroup, offerings, 'orderNumber', 'name');
console.log(offerings);

Check if nested arrays in object contains empty values

Consider the following object:
{
"params": {
"time_to_diagnosis": [
{
"field": "date_of_diagnosis",
"value": ""
},
{
"field": "date_of_symptom_onset",
"value": "2019-09-01"
}
],
"time_since_onset": [
{
"field": "date_of_symptom_onset",
"value": "2019-09-01"
}
]
}
}
As you can tell this is a object , of objects with arrays that them selves contains objects.
As you can see some keys are empty.
The idea is that if there are no empty keys in the arrays containing objects, then return true, else return false.
Heres what I wrote:
const isParamsInAjaxParamsEmpty = (paramsForAjaxCall) => {
for (const key in paramsForAjaxCall) {
for (const nestedKey in paramsForAjaxCall[key]) {
const params = paramsForAjaxCall[key];
if (params[nestedKey] === "") {
return true;
}
}
}
return false;
}
I Know I can do an Array.isArray on the nestedKey part, but Im not sure how to make this recursive, as there could be one or more arrays.
paramsForAjaxCall is the object above.
Thoughts?
you can map the array then take the values from the Object and with every will get a boolean value so it's an array of booleans in the end because we mapping.
if this array contains a false so the result is false
const data = {
"params": {
"time_to_diagnosis": [{
"field": "date_of_diagnosis",
"value": "ddd"
},
{
"field": "date_of_symptom_onset",
"value": "2019-09-01"
}
],
"time_since_onset": [{
"field": "date_of_symptom_onset",
"value": "2019-09-01"
}]
}
}
const res = !Object.values(data).map(o => Object.values(o).map(value => value.every(({
value
}) => value !== ""))).flat().includes(false)
console.log(res)
You could take a check for not object and return false, then check for the wanted property or iterate all properties.
function check(object) {
if (!object || typeof object !== 'object') return false;
if (object.value) return true;
return Object.values(object).every(check);
}
var object = { params: { time_to_diagnosis: [{ field: "date_of_diagnosis", value: "" }, { field: "date_of_symptom_onset", value: "2019-09-01" }], time_since_onset: [{ field: "date_of_symptom_onset", value: "2019-09-01" }] } }
console.log(check(object));
object.params.time_to_diagnosis[0].value= "foo";
console.log(check(object));

Categories

Resources