How to change original array based on other array - javascript

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}`)
}))

Related

Unable to update a JSON value

I'm writing a code where I need to filter a JSON array and update a value of a key. Here is my code.
var data = [{
"Id": "1",
"ab": '123',
"afb_Educational_expense_types_for_school__c": "Books or supplies"
}, {
"Id": "2",
"ab": '343',
"afb_Educational_expense_types_for_school__c": "Mandatory fees"
}, {
"Id": "3",
"ab": '34',
}];
var itemVar = data.filter(item => item.Id == '3');
itemVar['ab'] = '22';
console.log(itemVar);
Here I'm trying to set 'ab' to 22 but it is not working. Where am I going wrong?
Your itemVar is an array, because .filter always returns an array. You have to specify that you want the first element in the array [0]
itemVar[0]['ab'] = '22';
You can use findIndex and then update the relevant item of the array:
const data = [
{ "Id": "1", "ab": '123', "afb_Educational_expense_types_for_school__c": "Books or supplies" },
{ "Id": "2", "ab": '343', "afb_Educational_expense_types_for_school__c": "Mandatory fees" },
{ "Id": "3", "ab": '34' }
];
let index = data.findIndex((item) => item.Id == '3');
if (index !== -1) data[index].ab = '22';
console.log(data);
var itemVar = data.find((item) => item.Id == '3')
itemVar.ab = '22'
Thats the easiest way to solve it.

Filter on two arrays same time?

I have two arrays:
const array1 = [{
"id": "4521",
"name": "Tiruchirapalli",
"stateId": "101"
},
{
"id": "1850",
"name": "Tenkasi",
"stateId": "101"
},
{
"id": "202",
"name": "Thanjavur",
"stateId": "101"
},
{
"id": "505",
"name": "Ernakulam",
"stateId": "102"
},
];
And now array2
const array2 = [{
"id": 1850,
"cityName": "Tenkasi",
"aliasNames": [
"Thenkasi"
]
},
{
"id": 4521,
"cityName": "Tiruchirapalli",
"aliasNames": [
"Trichy"
]
},
{
"id": 202,
"cityName": "Thanjavur",
"aliasNames": [
"Tanjore"
]
},
{
"id": 505,
"cityName": "Ernakulam",
"aliasNames": [
"Kochi",
"Cochin"
]
},
];
what i need to do is, how to filter both the arrays at same time ( or filter first one and then second which ever one is performance effective ).
For instance, when user types "Kochi", first it should check on array1 to find if its has name="Kochi", if it has then we can set the state with that and if it doesnt have we need to find it on array2 and the update the state !
Which is fast and effective way to handle this - ( array1 has 2500 records and array2 has 990 records ) so performance / speed is also a concern
My attempt:
searchFilterFunction = text => {
this.setState({ typedText: text });
const newData = array1.filter(item => {
const itemData = `${item.name.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
this.setState({ data: newData});
};
How to implement the second filter in optimized way ?
For instance, when user types "Kochi", first it should check on array1
to find if its has name="Kochi", if it has then we can set the state
with that and if it doesnt have we need to find it on array2 and the
update the state !
I would do something like this with Array.find.
if( array1.find(item=>item.name.toUpperCase() === text) ) {
// set state
} else if( array2.find(item=>item.cityName.toUpperCase() === text) ) {
// set state
}
A refined form would be
let result = array1.find(item=>item.name.toUpperCase() === text);
// check in array 2 as we cannot find in array 1
if(!result) {
result = array2.find(item=>{
// check in aliasNames and in cityName
return item.cityName.toUpperCase() === text || item.aliasNames.includes(text);
}
);
}
if(result) {
setState(result);
} else {
// place not found
}
Regarding the performance based on your array count you will not see much difference. If you want to save some milliseconds you can check the array with least count first as mentioned in one of the comments. But the time also varies based on were the element is in array.
I think this is the most optimal solution because nesting the two filter won't work as you need to filter from first array and then second.
const array1 = [{
"id": "4521",
"name": "Tiruchirapalli",
"stateId": "101"
},
{
"id": "1850",
"name": "Tenkasi",
"stateId": "101"
},
{
"id": "202",
"name": "Thanjavur",
"stateId": "101"
},
{
"id": "505",
"name": "Ernakulam",
"stateId": "102"
},
];
const array2 = [{ "id": 1850, "cityName": "Tenkasi",
"aliasNames": [
"Thenkasi"
]
},{"id": 4521,"cityName": "Tiruchirapalli",
"aliasNames": [
"Trichy"
]
},
{
"id": 202,
"cityName": "Thanjavur",
"aliasNames": [
"Tanjore"
]
},
{
"id": 505,
"cityName": "Ernakulam",
"aliasNames": [
"Kochi",
"Cochin"
]
},
];
function filter(text) {
// Complexity Linear
const filter_array = array1.filter((a) => {
return (a.name === text)
});
if (filter_array.length > 0) {
//Set State and return
}
//Complexity Linear and includes complexity Linear O(sq(m*n)) where n is //the aliasName record
const filter_array2 = array2.filter((a) => {
return a.cityName === text || a.aliasNames.includes(text);
});
return filter_array2 //Set State filter array 2
}
console.log(filter("Kochi"));

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

Iterating a Json object and storing the end result

I am trying to iterate a JSON object which is an array of categories.The categories may or may not have the subcategory.
If
hasSubcategory = false ,
then category id should be stored in final array.
If hasSubcategory = true ,it should iterate until the subcategory becomes hasSubcategory = false and store id in
final array.
There is parentId field to represent the parent category of the category.
More Importantly there may be sub categories for a single sub category
The final array should only be have the id of categories with hasSubcategory = false .
I would advise to chain filter + map methods:
const arr = [
{
"_id": "1",
"name": "DESKTOP COMPUTERS",
"hasSubCategory": "true",
"parentId": "0"
},
{
"_id": "2",
"name": "LAPTOP COMPUTERS",
"hasSubCategory": "false",
"parentId": "1"
},
{
"_id": "3",
"name": "MONITORS",
"hasSubCategory": "false",
"parentId": "2"
},
{
"_id": "4",
"name": "INPUT DEVICES",
"hasSubCategory": "true",
"parentId": "0"
},
{
"_id": "5",
"name": "PRINTERS SCANNERS",
"hasSubCategory": "false",
"parentId": "4"
},
{
"_id": "6",
"name": "ACCESSORIES",
"hasSubCategory": "false",
"parentId": "4"
},
];
const result = arr.filter(el => el.hasSubCategory === 'false').map(el => el._id);
console.log(result);
This is really simple - just use filter to extract the items with hasSubCategory of false, then map out the _id:
const arr = [{"_id":"1","name":"DESKTOP COMPUTERS","hasSubCategory":"true","parentId":"0"},{"_id":"2","name":"LAPTOP COMPUTERS","hasSubCategory":"false","parentId":"1"},{"_id":"3","name":"MONITORS","hasSubCategory":"false","parentId":"2"},{"_id":"4","name":"INPUT DEVICES","hasSubCategory":"true","parentId":"0"},{"_id":"5","name":"PRINTERS SCANNERS","hasSubCategory":"false","parentId":"4"},{"_id":"6","name":"ACCESSORIES","hasSubCategory":"false","parentId":"4"}];
const res = arr.filter(({ hasSubCategory }) => hasSubCategory == "false").map(({ _id }) => _id);
console.log(res);
For a more efficient solution, use reduce:
const arr = [{"_id":"1","name":"DESKTOP COMPUTERS","hasSubCategory":"true","parentId":"0"},{"_id":"2","name":"LAPTOP COMPUTERS","hasSubCategory":"false","parentId":"1"},{"_id":"3","name":"MONITORS","hasSubCategory":"false","parentId":"2"},{"_id":"4","name":"INPUT DEVICES","hasSubCategory":"true","parentId":"0"},{"_id":"5","name":"PRINTERS SCANNERS","hasSubCategory":"false","parentId":"4"},{"_id":"6","name":"ACCESSORIES","hasSubCategory":"false","parentId":"4"}];
const res = arr.reduce((a, { hasSubCategory, _id }) => (hasSubCategory == "false" ? a.push(_id) : a, a), []);
console.log(res);
Filter first to get the objects you need, then map them into the pattern you need.
let arr = [{"_id":"1","name":"DESKTOP COMPUTERS","hasSubCategory":"true","parentId":"0"},{"_id":"2","name":"LAPTOP COMPUTERS","hasSubCategory":"false","parentId":"1"},{"_id":"3","name":"MONITORS","hasSubCategory":"false","parentId":"2"},{"_id":"4","name":"INPUT DEVICES","hasSubCategory":"true","parentId":"0"},{"_id":"5","name":"PRINTERS SCANNERS","hasSubCategory":"false","parentId":"4"},{"_id":"6","name":"ACCESSORIES","hasSubCategory":"false","parentId":"4"}];
res = arr.filter(v => v.hasSubCategory === "false").map(e => Number(e._id))
console.log(res) // [ 2, 3, 5, 6 ]
Alternatively you can use reduce too:
let arr = [{"_id":"1","name":"DESKTOP COMPUTERS","hasSubCategory":"true","parentId":"0"},{"_id":"2","name":"LAPTOP COMPUTERS","hasSubCategory":"false","parentId":"1"},{"_id":"3","name":"MONITORS","hasSubCategory":"false","parentId":"2"},{"_id":"4","name":"INPUT DEVICES","hasSubCategory":"true","parentId":"0"},{"_id":"5","name":"PRINTERS SCANNERS","hasSubCategory":"false","parentId":"4"},{"_id":"6","name":"ACCESSORIES","hasSubCategory":"false","parentId":"4"}];
res = arr.reduce((a,c) => {if (c.hasSubCategory === "false") a.push(Number(c._id)); return a;}, [])
console.log(res)

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

Categories

Resources