I used map to loop but it returned an array, not sure I should use something else like forEach. I have this initial object.
data.discounts: [{
days: 3,
is_enable: true
},{
days: 10,
is_enable: false
}]
Then I do the checking on is_enable
const newObj = {
"disableDiscount_3": !isEmpty(data.discounts) ? (data.discounts.map(obj => obj.days === 3 && obj.is_enable === true ? true : false)) : ''
}
then it became
newObj.disableDiscount_3 = [{
true,
false,
false,
false
}]
What I want is actually just true or false like: newObj.disableDiscount_3 = true What should I do?
map() method is not meant to be used for that, instead you can use some() that will check if specified object exists and return true/false.
var discounts = [{
days: 3,
is_enable: true
}, {
days: 10,
is_enable: false
}]
var check = discounts.some(e => e.days == 3 && e.is_enable === true);
console.log(check)
To first find specific object you can use find() method and if the object is found then you can take some property.
var data = {
discounts: [{
days: 3,
is_enable: true,
value: 123
}, {
days: 10,
is_enable: false
}]
}
var obj = {
"discount_3": (function() {
var check = data.discounts.find(e => e.days == 3 && e.is_enable === true)
return check ? check.value : ''
})()
}
console.log(obj)
Related
Hi i have an array of objects that i want to sort based on a boolean that one of the objects has. However normally there would be either true or false but in this case we also check on null values because sometimes the data has not been set and in that case we wanna show that it has yet to be set with an icon.
Here's an example of the array:
const arrayOfObjects = [
{
id: 69,
boolean: true,
name: 'foo',
},
{
id: 42,
boolean: false,
name: 'bar',
},
{
id: 666,
boolean: null,
name: 'foo',
},
{
id: 420,
boolean: false,
name: 'bar',
},
{
id: 2,
boolean: null,
name: 'foo',
},
{
id: 123,
boolean: true,
name: 'foo',
},
]
So what i tried first was:
arrayOfObjects.sort((a, b) => b.boolean - a.boolean);
This sets the objects that are true at the front but the objects with false or null are scattered.
Then i tried:
arrayOfObjects.sort((a, b, c) => (c.boolean - b.boolean) - a.boolean);
This just didn't work at all.
I couldn't really find a case that was similar enough to base a solution off of it so hopefully i can find it here.
If you like to use a custom sorting, you could take an object with the wanted sorting, like
const
order = { true: 1, null: 2, false: 3 };
data = [{ id: 69, boolean: true, name: 'foo' }, { id: 42, boolean: false, name: 'bar' }, { id: 666, boolean: null, name: 'foo' }, { id: 420, boolean: false, name: 'bar' }, { id: 2, boolean: null, name: 'foo' }, { id: 123, boolean: true, name: 'foo' }];
data.sort((a, b) => order[a.boolean] - order[b.boolean]);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you have unknown values and want to move them to bottom, you could add another key with a large value, like
order = { true: 1, null: 2, false: 3, bottom: Number.MAX_VALUE };
Usage:
data.sort((a, b) =>
(order[a.boolean] || order.bottom) - (order[b.boolean] || order.bottom)
);
You can check for the null explicitly ...
let list = [{i: 0, boolean: true}, { i: 1, boolean: null}, { i:2, boolean: false}, { i: 4, boolean: true}]
function cpBoolWithNull(a,b) {
//if both are null return 0 to maintain a stable sort
//if only one is null return 0 or 1 depending on the value of the other
if (a.boolean === null) return b.boolean === null ? 0 : b.boolean ? 1 : -1;
if (b.boolean === null) return a.boolean ? -1 : 1;
//if both are different from null, sort true before false
return b.boolean - a.boolean
}
console.log(list.sort(cpBoolWithNull));
This will sort true ... null ... false If you need a differnt order, adjust the return values.
I think that you can have a type checker with JS with this simple script.
let array =[true, false, null];
function check(i){
if (array[i] != null||array[i]!=false){
if (array[i]!=null || array[i]!=true)document.write(" Array item"+" "+i+" "+"has the value of boolean false. ");
if (array[i]!=true||array[i]!=false)document.write(" Array item"+" "+i+" "+"has the value of boolean true. ");
if (array[i] != true || array[i] != false )document.write(" Array item"+" "+i+" "+"has the value of object null. ");
document.write("<br>")
}
}
check(0);
You can comment out the other text when it is not needed.
This:
const pageID: number = 4;
and this:
this.charts.findIndex((chart: IChart) => {
return chart.pageID === pageID;
}));
this.charts is an array of IChart[] which contains:
[
{
"pageID": 3,
"zoomable": false
},
{
"pageID": 4,
"zoomable": false
},
{
"pageID": 5,
"zoomable": false
}
]
Amazingly, this always returns -1. Even if I change the value of pageID to 4 or 5.
Usually this works, but it's driving me nuts. The only thing I am doing before trying to find the index is merging two arrays and removing duplicate values based on the pageID parameter, like this:
let unique = {};
this.charts = charts[0].concat(charts[1])
.filter((chart) => !unique[chart.pageID] && (unique[chart.pageID] = true))
.sort((a, b) => a.pageID - b.pageID);
The output of this.charts is the array pasted above with zoomable and pageID properties.
--
It's not rocket science even running the above in the proper sequence inside node returns the proper index which is 1 in my case. Does anyone have any insights on this issue?
Note: this is running in a Cordova app on iOS wkwebview.
Thank you.
Your code seems to run just fine.
const allCharts = [[
{ 'pageID': 3, 'zoomable': false },
{ 'pageID': 4, 'zoomable': false },
{ 'pageID': 5, 'zoomable': false }
], [
{ 'pageID': 3, 'zoomable': false },
{ 'pageID': 6, 'zoomable': false },
{ 'pageID': 7, 'zoomable': false }
]];
let unique = {};
const charts = allCharts[0].concat(allCharts[1])
.filter(chart => !unique[chart.pageID] && (unique[chart.pageID] = true))
.sort((a, b) => a.pageID - b.pageID);
const pageID = 4;
const idx = charts.findIndex(chart => {
return chart.pageID === pageID;
});
console.log(JSON.stringify(charts));
console.log('idx of pageId 4 is:', idx);
I want to check each object in an array to see if certain things exist. So let's say my array looks like this:
const arrayOfItems = [
{
delivery_method: {
delivery_method: 'car',
delivery_rate: 1,
pickup_day: 'none',
},
total_cost: 5,
items: [{}],
},
{
delivery_method: {
delivery_method: 'pickup',
pickup_day: 'T',
delivery_rate: 0,
},
total_cost: 5,
items: [{}],
},
]
And now I have a check methods function that looks like this:
async checkMethodChosen() {
let check = await arrayOfItems.map((item) => {
if (
(item.delivery_method.delivery_method === 'pickup'
&& item.delivery_method.pickup_day !== 'none')
|| item.delivery_method.delivery_method === 'car'
|| item.delivery_method.delivery_method === 'bike'
) {
return false
}
return true
})
let deliveryChosen = check.includes(false)
this.setState({
deliveryChosen,
})
}
The function sets the state with true or false if delivery_method is set to 'pickup' and the pickup_day is selected OR if delivery_method === 'car' or 'bike' . This works fine if there's only one object in the array. It's not working if there are multiple objects.
What I want to happen is if there are multiple objects, then this.state.deliveryChosen should only be true if delivery_method has been selected in each object. If it hasn't been selected for one object, then this.state.deliveryChosen should be false.
Thanks!
The function you are looking for is every() it will return true if the callback returns true for every item in an array.
For example here's a simplified version that just returns the boolean:
const arrayOfItems = [{delivery_method: {delivery_method: 'car',delivery_rate: 1,pickup_day: 'none',},total_cost: 5,items: [{}],},{delivery_method: {delivery_method: 'pickup',pickup_day: 'T',delivery_rate: 0,},total_cost: 5,items: [{}],},]
function checkMethodChosen(arr) {
// will return true if every item of arr meets the following condition:
return arr.every((item) =>
(item.delivery_method.delivery_method === 'pickup' && item.delivery_method.pickup_day !== 'none')
|| item.delivery_method.delivery_method === 'car'
|| item.delivery_method.delivery_method === 'bike'
)
}
console.log(checkMethodChosen(arrayOfItems))
I have this array burgerActions :
[
{
statusId: 2,
label: 'Accept'
},
{
statusId: 3,
label: 'Reject'
},
{
label: 'Consult'
},
{
label: 'Transfer'
}
]
and this object status which can be either :
{
"label": "Accept",
"id": 2
}
or :
{
"label": "Reject",
"id": 3
}
In a first case you have to create a new array from burgerActions array where the statusId is not equivalent to the id of the status object that we have (we can only have one status object of the 2 cases that I listed).
For that I used the filter method :
const result = burgerActions.filter((element) => {
return element.statusId !== recommendation.status.id
})
In the second case I need a complex conditioning adding with boolean
const statusRef = recommendation.recipient
In a first case I want if statusRef is false filter the last object in the burgerAction ({label: 'Transfer'}) but not in the case if statusRef is true.
I need a method that does this type of filter without using the if () conditions because there are several cases to handle.
If you want to filter the objects that doesn't have the same statusId as in the recommendation.status.id and if recommendation.recipient === true filter the ones that doesn't have statusId, you can use this condition in the filter callback function:
element.statusId !== recommendation.status.id && recommendation.recipient ? element.statusId != null : true;
Where && recommendation.recipient ? element.statusId != null : true means that if recommendation.recipient is true filter elements with a statusId.
Here's how should be your code:
var recommendation = {
status: {
"label": "Pending",
"id": 1
},
recipient: true
};
const result = burgerActions.filter((element) => {
return element.statusId !== recommendation.status.id && recommendation.recipient ? element.statusId != null : true;
});
Demo:
var burgerActions = [{
statusId: 2,
label: 'Accept'
},
{
statusId: 3,
label: 'Reject'
},
{
label: 'Consult'
},
{
statusId: 1,
label: 'Transfer'
}
];
var recommendation = {
status: {
"label": "Pending",
"id": 1
},
recipient: true
};
const result = burgerActions.filter((element) => {
return element.statusId !== recommendation.status.id && recommendation.recipient ? element.statusId != null : true;
});
console.log(result);
This question is for purely for learning purposes. funfunfunction on youtube says that
Any list higher order list transformation can be written in Array.reduce()
Audio/video Reference: https://youtu.be/Wl98eZpkp-c?t=138.
Question:
Purely for learning how would one rewrite Array.every() with Array.reduce()
This question stems from my previous question here
Javascript Example:
var approved1 = [
{
dateApproved: new Date(),
id: 1,
},
{
dateApproved: new Date(),
id: 2,
}
];
var approved2 = [
{
dateApproved: null,
id: 1,
},
{
dateApproved: new Date(),
id: 2,
}
];
approved1.every(a => a.dateApproved != null) ? 'APPROVED' : 'PENDING'
// 'APPROVED'
approved2.reduce(every) ? 'APPROVED' : 'PENDING'
// 'PENDING'
I struggle with where I store the currently passed values. Where do I store the "passed" values like Array.every() does?
function every(previousValue, currentValue, currentIdx, arr) {
if(previousValue.dateApproved !== null && currentValue.dateApproved !== null) {
return currentValue;
}
}
You can use reduce instead of every and make it work, but I'd suggest you to use them in there apt places. Both have distinctive requirement.
array.reduce
array.reduce(callback(curentElement, nextElement, index, array),[initialCurrentElement])
Array.reduce has 4 args.
currentElement: By default, this will be 1st element in array for 1st iteration and then, this variable will hold value that you return. If an initial value is passed, then it will hold that and start from there.
nextElement: By default it holds second or next element. If initial value is passed, this will hold first value.
index: this holds the index of current element.
array: This is the parent array on which we are looping.
initialCurrentElement: This is an optional argument. If this is passed, looping starts with this.
Following is a sample showing an illustration:
Note:
Array.every will break on first falsey condition. Array.reduce will not.
Array.reduce is meant to compare 2 values of same array where as Array.every is meant to compare each values to an expression. Using .reduce instead of .every is just an overkill.
var approved2 = [{
dateApproved: null,
id: 1,
}, {
dateApproved: new Date(),
id: 2,
}];
var everyResult = approved2.every(x => {
console.log(x.dateApproved)
x.dateApproved !== null
})
console.log(everyResult)
var reduceResult = approved2.reduce((p, c) => {
console.log(c.dateApproved)
return !p ? p : c.dateApproved !== null
}, true)
console.log(reduceResult? 'Approved': 'Rejected')
This should do the trick:
function every(pre, curr) {
return pre.dateApproved != null && curr.dateApproved != null
}
approved1.reduce(every) ? 'APPROVED' : 'PENDING' // APPROVED
approved2.reduce(every) ? 'APPROVED' : 'PENDING' // PENDING
And I'm pretty sure you can do it without curr, just pre.
var status = approved1.reduce( val => (val.dateApproved) ? 'APPROVED': 'REJECTED')
var approved1 = [
{
dateApproved: new Date(),
id: 1,
},
{
dateApproved: new Date(),
id: 2,
}
];
var approved2 = [
{
dateApproved: new Date(),
id: 1,
},
{
dateApproved: null,
id: 2,
},
{
dateApproved: new Date(),
id: 2,
}
];
console.log(approved2.reduce( (prev, curr) => (prev.dateApproved && curr.dateApproved) ? true : false) ? 'APPROVED':'REJECTED')
console.log(approved1.reduce( (prev, curr) => (prev.dateApproved && curr.dateApproved) ? true : false) ? 'APPROVED':'REJECTED')
You might roughly implement it as folows
Array.prototype.every = function(cb){
return this.reduce((p,c,i,a) => i === 1 ? cb(p,i-1,a) && cb(c,i,a)
: p && cb(c,i,a));
};
var arr = [9,2,3,9,12,5],
brr = [1,2,3,4,5,6,9];
console.log(arr.every(e => e < 10));
console.log(brr.every(e => e < 10));