simplest way to remove key value data from javascript object - javascript

What is the simplest way to "afterpaypayovertime" key & value data from below object ?
let getPayments = available_payment_methods.filter(item => {
return checkoutData.paymentOptions.find(value => item.code === value.payment_method);
});
//Output object
getPayments = [
{
"payment_method": "afterpaypayovertime",
"payment_label": "Afterpay"
},
{
"payment_method": "paypal_express",
"payment_label": "PayPal"
},
{
"payment_method": "stripe_payments",
"payment_label": "New Card"
}
]

You can simply do something like this to get the desired results.
let newPaymentObj = getPayments.filter(paymentObject => paymentObject.payment_method !== 'afterpaypayovertime')
console.log(newPaymentObj)
the filter method provide you another array based on the condition that you pass to the callback function. In this case you are simply telling the filter method that you want to get every element in the array whose payment_method is not afterpaypayovertime

Related

Typescript filter to select object with value of specific words

I have an array of objects in my DB records.
The record:
{"ID123":{"FileID":"12345","FileName":"ABCFile_ver5_44453.PDF"},"DocID":6009,"DocFormat":"PDF"}
The format to store the filename in my DB is always with "FileName": "actual_fileName.PDF".
I want to only get the object with "FileName":"....", to only display the filename instead of other objects.
This is my code:
getValue(): Atts[] | any {
if (this.isEmptyValue()) {
return [];
}
return !this.useObject ? this.value : Object.entries(this.value).map(([key, value]) => ({ key, value })).filter(value=);
}
How do I filter the object that contains "FileName" so that I can display the filename in my application?
I'm stuck at the filter method.
I had to reduce your code a little to a minimal reproducible example, and I made the assumption that this.value in your Object.entries is the entire DB record that you have listed above. I converted this to an object so I could process it in my code. So, your mileage may vary if my assumption was incorrect.
let obj = {
"ID123": {
"FileID": "12345",
"FileName": "ABCFile_ver5_44453.PDF"
},
"DocID": 6009,
"DocFormat": "PDF"
};
let result = { "FileName": Object.entries(obj).map(([key, value]) => ({
key,
value
})).filter(keyValuePair => {
if (keyValuePair.value.FileName) {
return true;
}
})[0].value.FileName };
This returns:
{
"FileName": "ABCFile_ver5_44453.PDF"
}
Your filter step is filtering an array of key value pairs, so when filtering, you need to return true only if the 'value' is an object that has a property of FileName.
EDIT:
I realized that the way I wrote this will not work if the returned object from the array does not have value (or is undefined), so it's probably a better idea to store this in a variable first, and then return an object based on that varible, like so:
let fileNameObj = Object.entries(obj).map(([key, value]) => ({
key,
value
})).filter(keyValuePair => {
if (keyValuePair && keyValuePair.value.FileName) {
return true;
}
})[0];
if (fileNameObj && fileNameObj.FileName) {
let result = { "FileName": fileNameObj.FileName };
}

Alternative to eval for converting a string to an object

I have a function that is using eval to convert a string with an expression to an object based on the parameter.
let indexType = ["Mac", "User", "Line", "Mask", "Ip", "Location"]
const filterIndex = (item) => {
filteredIndexSearch = []
eval(`search${item}`).forEach((e) => filteredIndexSearch.push(searchData[e.key]))
}
filterIndex(indexType[searchTotal.indexOf(Math.max(...searchTotal))])
searchData is an array that returns values based on the user input.
searchTotal is an array with the length of each search{item} array.
The filterIndex function takes the highest value from the searchData array and corresponds it to the indexType array, then use eval to convert the string to an object to pass the value to the filteredIndexSearch array.
What would be a better alternative to eval?
EDIT
To add more information on what this does:
searchData = [
[
{
key: 1,
data: "0123456789101"
},
{
key: 1,
data: "John Smith"
}
],
[
{
key: 2,
data: "0123456789102"
},
{
key: 2,
data: "Jane Smith"
},
]
]
const search = (data, key, container) => {
if (!data) data = "";
if (data.toLowerCase().includes(string)) {
container = container[container.length] = {
key: key,
data: data
}
}
}
const returnSearch = () => {
for (let i = 0; i < searchData.length; i++) {
search(searchData[i][0].data, searchData[i][0].key, searchMac)
search(searchData[i][1].data, searchData[i][1].key, searchUser)
}
}
returnSearch()
The data is incomplete, but hopefully conveys what I'm trying to do.
search will take the user input, and store the information in the corresponding array. If I input "Jo", it will return the searchUser array with only the "John Smith" value and all the other values with the same key. Inputting "102" returns the searchMac with the "0123456789102" value and all other values with the same key.
At the end of the day. I just want to convert search${parameter} to an object without using eval.
Move your global arrays into an object.
Somewhere it appears that you're defining the arrays, something like:
searchMac = [...];
searchUser = [...];
...
Instead of defining them as individual arrays, I'd define them as properties in an object:
searchIndices.Mac = [...];
searchIndices.User = [...];
...
Then, instead of using eval, your can replace your eval().forEach with searchIndices[item].forEach.
If the order of your search isn't important, your can instead loop through the keys of searchIndices:
Object.keys(searchIndices).forEach(item => {
searchIndices[item].forEach(...);
});
This ensures that if you ever add or drop an entry in searchIndices, you won't miss it or accidentally error out on an undefined search index.
Any time you have a situation with variables named x0, x1 etc, that should be a red flag to tell you you should be using an array instead. Variable names should never be semantically meaningful - that is code should never rely on the name of a variable to determine how the code behaves. Convert search0 etc into an array of search terms. Then use:
const filterIndex = (item) => search[item].map(i => searchData[i.key]);
filteredIndexSearch = filterIndex(indexType[searchTotal.indexOf(Math.max(...searchTotal))]);
(simplifying your code). Note that in your code, filteredIndexSearch is modified inside the arrow function. Better to have it return the result as above.

Use regex to access object's fields

I am in a situation in which I may need to process a JSON that could contain varying key names, which I'd need to access via regex.
For simplicity, I could receive a list similar to:
x=[{ bus: "XYZ123", color:"red" },
{ minibus: "ZZZ999", color:"blue" } ]
and I need to have a function that could get XYZ123 and ZZZ999 within a map function.
I've tried x.map( e => e[/.*bus/]) but to no avail, returning [undefined,undefined]
Does anyone have any trick I could follow for this?
Thank you
var x = [{
bus: "XYZ123",
color: "red"
},
{
minibus: "ZZZ999",
color: "blue"
}
];
console.log(
x.map(it => it[Object.keys(it).find(key => key.endsWith('bus'))])
);
This version of the logic gets all the keys, and then finds the key that ends with bus. Assuming there is only one per object, it gets the first one, and then returns that keys value in each object.
You can use a for ... in loop to find a property name on an object by matching a regular expression.
const regex = /.*bus/;
const result = x.map((e) => {
for (var key in e) {
if (key.match(regex)) {
return e[key];
}
}
return undefined;
});
console.log(result);
Map return mapping... one to one. so if some of your data in array don't fulfills your condition then you return an undefined value on this index in array. eg.if you have array that have 100 items, and only 5 fulfills your condition, then a map will return 100 elements in 95 cases you will get undefined. You should use filter, if you need a new copy of your array you can just create it.
const x=[{ bus: "XYZ123", color:"red" },
{ minibus: "ZZZ999", color:"blue" } ,
{ motobicke: "ZZZ999", color:"black" } ]
const filterBy = (data, regex) => {
return Array.from(data).filter(item => Object.keys(item).some(key => regex.test(key)) )
}
console.log(filterBy(x, /bus/));

Find nested object that contains a value

I have an object containing multiple other objects, inside these nested objects is an array containing multiple objects, each with a uid. I'm trying to loop over the objects and find the object that contains a particular uid.
My data looks like this
const data = {
"3c5671fde44f44f9ad59d59eb810d87e": {
"heading": "Heading 1",
"items": [
{
"content": {
"uid": "4fcd5f4af7a448d48463d4e0a11297d9"
}
},
{
"content": {
"uid": "31f975440a0a431592e127b2891cd142"
}
}
]
},
"ea80e8315b554c9bb40958a6cacf4b0c": {
"heading": "Heading 2",
"items": [
{
"content": {
"uid": "d6de8db4c2a74da6915a44d3964277d6"
}
}
]
}
}
The uid I want to search for is d6de8db4c2a74da6915a44d3964277d6 when found I want to return it's parent object so I can access the heading property.
Current code looks like this but it doesn't work, it's been a long day so I'm likely missing something really simple.
const currentUid = "d6de8db4c2a74da6915a44d3964277d6";
const currentHeading = Object.keys(data).forEach(section => {
return data[section].items.filter(item => {
return item.content.uid === currentUid;
});
});
When debugging it successfully evaluates to true when it finds the correct uid, it just doesn't return anything.
Any help welcome!
forEach is meant just for looping the array, use find to find the key of your object from Object.keys(data). And inside the callback use some instead of filter to check the existance. This solution will result in either the key of the object or null. To get the object, just check that a key is returned and then use that key to get the object:
const currentHeadingKey = Object.keys(data).find(section => {
return data[section].items.some(item => {
return item.content.uid === currentUid;
});
});
const currentHeading = currentHeadingKey != null ? data[currentHeadingKey] : null;
currentHeading is now either the whole object if found, null otherwise. You can access the heading property of that object.
Note: Since the callbacks of both find and some have only one statement in them, you can use the implicit return of arrow function to shorten the code:
const currentHeadingKey = Object.keys(data).find(section =>
data[section].items.some(item => item.content.uid === currentUid)
);
Consider using the Object.values() method instead, to extract the "parent heading" for the supplied uid.
Taking this approach, you can iterate the values of data, and filter those section values that contain items matching the uid. In the answer below, this is done via:
return items.some(item => item.content.uid === currentUid)
Finally, you can map() the filtered sections to acquire the corresponding heading(s) of section with matching uid items:
function findHeading(data, uid) {
return Object.values(data).filter(section => {
// Find any item with matching uid in this section, filter this section accordingly
return section.items.some(item => item.content.uid === currentUid)
})
.map(section => {
// Map heading from any sections matching item uid
return section.heading
});
}
const data = {
"3c5671fde44f44f9ad59d59eb810d87e": {"heading": "Heading 1","items": [{"content": {"uid": "4fcd5f4af7a448d48463d4e0a11297d9"}},{"content": {"uid": "31f975440a0a431592e127b2891cd142"}}]},"ea80e8315b554c9bb40958a6cacf4b0c": {"heading": "Heading 2","items": [{"content": {"uid": "d6de8db4c2a74da6915a44d3964277d6"}}]}
}
const currentUid = "d6de8db4c2a74da6915a44d3964277d6";
console.log(findHeading(data, currentUid))

JavaScript object array filtering with embedded array

I have an object that looks like the following:
let responseData = [
{
"name": "name",
"other": "value",
"anotherField": "blue",
"appRoles": [
{
"code": "roleOne",
"shouldDisplay": true
},
{
"code": "roleTwo",
"shouldDisplay": false
}
]
}
I need to maintain the original structure all while keeping existing properties. I only want to remove/filter out any "appRoles" where "shouldDisplay" is false.
The following works, using a forEach and a filter operation to create a new object array, but is it possible to condense this even more?
let filteredApps;
responseData.forEach((team) => {
let indyTeam = team;
indyTeam.appRoles = team.appRoles.filter((role) => role.shouldDisplay === true);
filteredApps.push(indyTeam);
});
When I use the map operation, I only get an array of the filtered appRoles - missing extra properties on each object such as "name":
let enabledAppRolesOnly =
responseData.map((team) =>
team.appRoles.filter((role) => role.shouldDisplay === true));
array.map function calls a callback for each element of your array, and then push the return value of it to a new array.
from MDN doc:
map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values, including undefined. It is not called for missing elements of the array (that is, indexes that have never been set, which have been deleted or which have never been assigned a value).
So in your case, since you return team.appRoles.filter((role) => role.displayByDefault === true) which is your team array, you only get this.
What you could do would be this (in order to fully clone the object):
let responseData = [{
"name": "name",
"appRoles": [
{
"code": "roleOne",
"shouldDisplay": true
},
{
"code": "roleTwo",
"shouldDisplay": false
}
]
}]
let enabledAppRolesOnly = responseData.map(team => {
const appRoles = team.appRoles.filter(role => role.shouldDisplay === true)
return Object.assign({}, team, { appRoles })
});
console.log(enabledAppRolesOnly)
This will achieve your objective non-destructively. It will build a new array for you.
let responseData = [{
name: "name",
appRoles: [{
code: "roleOne",
shouldDisplay: true
}, {
code: "roleTwo",
shouldDisplay: false
}]
}];
let output = responseData.map(o => Object.assign({}, o, {
appRoles: o.appRoles.filter(r => r.shouldDisplay)
}));
console.log(responseData);
console.log(output);
Code explanation -
map
The map function iterates over the whole array and modifying the each item as specified this should be self evident.
Object.assign
This could be the tricky part -
o=>Object.assign({}, o, {appRoles: o.appRoles.filter(r=>r.shouldDisplay)})
From the docs Object.assign is used to copy values from the object.
The first argument {} causes a new object to be created.
The second argument o causes all props from the object o to be copied in the newly created object.
Now, note that we need to modify the appRoles property and keep only those roles which have shouldDisplay as true. That's exactly what the third argument does. It modifies the appRoles property and gives it the new value.
filter
Now the code -
o.appRoles.filter(r=>r.shouldDisplay)
should not be too difficult.
Here we keep only those roles which meet our criterion (namely shouldDisplay should be true)
If you look at the filter function, it expects the callback value to return a boolean value on whose basis it determines whether value has to be kept or not.
So the following code is not even required,
o.appRoles.filter(r=>r.shouldDisplay===true)
This is enough,
o.appRoles.filter(r=>r.shouldDisplay)
There's some missing information in the question. I'll assume the following:
filteredApps should only contain items where there's at least one appRole for display
it is OK if responseData and filteredApps contains references to the same team objects
there are no other references to team objects that need to keep the original data unaffected
As such, you can reduce your code down to this:
let filteredApps = responseData.filter(team =>
(team.appRoles = team.appRoles.filter(role => role.shouldDisplay)).length;
);
The result will be that each team will have only the .shouldDisplay members in its appRoles, and filteredApps will only have teams with at least one appRole with shouldDisplay being true.
You could build a new array with only part who are valid chinldren elements.
let responseData = [{ name: "name", appRoles: [{ code: "roleOne", shouldDisplay: true }, { code: "roleTwo", shouldDisplay: false }] }],
result = responseData.reduce((r, a) => {
var t = a.appRoles.filter(o => o.shouldDisplay);
if (t.length) {
r.push(Object.assign({}, a, { appRoles: t }));
}
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories

Resources