nested shape validation javascript - javascript

import get from "lodash.get";
const x = [
{
value: 1
},
{
value: {
min: undefined,
max: 2
}
}
];
console.log(
"valid: ",
x.every(o => o.value || (get(o, "value.min") && get(o, "value.max")))
);
https://codesandbox.io/s/modest-dijkstra-g42yy
I expect the valid to be false but it returned true although the value.min is undefined. What is the problem here?

The problem is that your first condition (o.value) returns true for the second item--since value is an object and therefore not falsy--so your check for min/max never runs.
const x = [
{
value: 1
},
{
value: {
min: undefined,
max: 2
}
}
];
// utility to check for null/undefined
const c = v => v != null;
console.log(x.every(({ value }) => (
typeof value === 'object'
? c(value.min) && c(value.max)
: c(value)
)));

Related

Delete a specific filtered element

In the datand object
I want to access Creaalues and
filter(startsWith('FL) && typeof el.value ===
'object')
Once I retrieve the field, I remove the array newly created and I push the data to a new object createalues.
I then want to add creatalue to the dataToSend Object
And I delete the element filtered from the initial createalues array
//original object
const datend = {
ID: 74,
crealues: [{
field: "F",
value: 'hello',
},
{
field: "F",
fileName: "doc.pdf",
value: {
field: 'FL',
fileName: 'bl.pdf',
value: 'jkhkjhkhkjh'
}
}
]
}
// code in progress
const test = dataToSend.creatlues.filter(
(el) => el.field.startsWith('FL') && typeof el.value === 'object'
);
datad.creatValues = test;
//output desired
const datnd = {
createValues: [{
field: "FLD_S",
value: 'hello',
}],
creatues: [{
field: "FL1",
value: 'hello',
}
],
creatlues:{
field: 'FL2',
fileName: 'bulletin_paie_avril.pdf',
value: 'jkhkjhkhkjh'
}
}
You should use splice using index of the element you want.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
You will need to use a loop;
const test = dataToSend.createValues.filter(
(el) => el.field.startsWith('FLD_STR_') && typeof el.value === 'object'
);
dataToSend.createFileValues = test;
test.foreach( ( obj ) => {
dataToSend.createValues.splice( 0, 1, obj );
}
If you really for some reason don't want to use a loop and you know you will ever only want 1 item then you could do
const test = dataToSend.createValues.filter(
(el) => el.field.startsWith('FLD_STR_') && typeof el.value === 'object'
);
dataToSend.createFileValues = test;
dataToSend.createValues.splice( 0, 1, test[0] );

&& operator returns 0 in JavaScript

I have an array of objects like this.
const items = [{ label : "foo" value : 1 },
{ label : "bar" value : 2 },]
When I have value1 = 1 value2 = 2 value3 = 0 , and execute this code.
[value1 && items.find(({value}) => value === value1).label,
value2 && items.find(({value}) => value === value2).label,
value3 && items.find(({value}) => value === value3).label,]
It returns result ["foo","bar",0] and 0 shows up on screen.
What I want is empty string instead of 0 like this ["foo","bar",""]
How I can do this?
You could take a default value.
const
items = [{ label: "foo" value: 1 }, { label: "bar" value: 2 }],
result = [1, 2, 3].map(v =>
v && state.items.find(({ value }) => value === v)?.label || '');
You could replace
value3 && items.find(({value}) => value === value3).label
with
value3 && (items.find(({value}) => value === value3).label ? 'your value' : '')

Need help by mapping a array

I have this Array with 6 different dates from db:
[{"_id":{"source":"2019-04-06","status":false},"count":1},
{"_id":{"source":"2019-04-06","status":true},"count":1},
{"_id":{"source":"2019-03-24","status":false},"count":2},
{"_id":{"source":"2019-03-24","status":true},"count":1},
{"_id":{"source":"2019-03-23","status":false},"count":3},
{"_id":{"source":"2019-03-08","status":false},"count":1},
{"_id":{"source":"2019-02-02","status":true},"count":1},
{"_id":{"source":"2019-02-02","status":false},"count":2},
{"_id":{"source":"2019-01-29","status":false},"count":1}]
What i need are 2 Arrays with the length of 6 items and the value of "count"
If only status "true" exists for a date, then i need to push a count: "0" to the false-array.
And if only status "false" exists for a date, then i need to push a count: "0" to the true-array.
It should look like this:
Arrayforstatusfalse = [1,2,3,1,2,1]
Arrayforstatustrue = [1,1,0,0,1,0]
But what i get is this:
Arrayforstatusfalse = [1,2,3,1,2,1]
Arrayforstatustrue = [1,1,1]
Update:
Sorry for this ugly code. i will be more precise. And thanks for your help.
this.responsedata = input
this.line1 = output for all the "false"
this.line2 = output for all the "true"
I loop over input data with condition and push it into the new arrays:
for (var i=0; i<this.responsedata.length;i++) {
if (this.responsedata[i]._id.status === true ) {
console.log('true exits for date: ' + JSON.stringify(this.responsedata[i]._id.source) + JSON.stringify(this.responsedata[i].count) )
this.line2.push(this.responsedata[i])
}
if (this.responsedata[i]._id.status === false ) {
console.log('false exits for date: ' + JSON.stringify(this.responsedata[i]._id.source) + JSON.stringify(this.responsedata[i].count) )
this.line1.push(this.responsedata[i])
}
}
Console :
[Log] false exits for date: "2019-04-06"1
[Log] true exits for date: "2019-04-06"1
[Log] false exits for date: "2019-03-24"2
[Log] true exits for date: "2019-03-24"1
[Log] false exits for date: "2019-03-23"3
[Log] false exits for date: "2019-03-08"1
[Log] true exits for date: "2019-02-02"1
[Log] false exits for date: "2019-02-02"2
[Log] false exits for date: "2019-01-29"1
[Log] line1[1,2,3,1,2,1]
[Log] line2[1,1,1]
And here i need line2 = [1,1,0,0,1,0]
because i need a 0 "if not exits on this date"..
You could take a Map for keeping the same index in insertation order of the given data.
var array = [{ _id: { source: "2019-04-06", status: false }, count: 1 }, { _id: { source: "2019-04-06", status: true }, count: 1 }, { _id: { source: "2019-03-24", status: false }, count: 2 }, { _id: { source: "2019-03-24", status: true }, count: 1 }, { _id: { source: "2019-03-23", status: false }, count: 3 }, { _id: { source: "2019-03-08", status: false }, count: 1 }, { _id: { source: "2019-02-02", status: true }, count: 1 }, { _id: { source: "2019-02-02", status: false }, count: 2 }, { _id: { source: "2019-01-29", status: false }, count: 1 }],
result = array.reduce((m => (r, { _id: { source, status }, count }) => {
var index = m.get(source);
if (index === undefined) {
m.set(source, index = m.size);
r.true[index] = 0;
r.false[index] = 0;
}
r[status][index] = count;
return r;
})(new Map), { true: [], false: [] }),
{ true: trues, false: falses } = result;
console.log(...trues);
console.log(...falses);
You can use reduce() to summarize the array into an object using the source as key. Convert the object into array using Object.entries and reduce it again to convert the inner child object into an array.
Use destructuring assignment syntax to assign into variables.
let array = [{"_id":{"source":"2019-04-06","status":false},"count":1},{"_id":{"source":"2019-04-06","status":true},"count":1},{"_id":{"source":"2019-03-24","status":false},"count":2},{"_id":{"source":"2019-03-24","status":true},"count":1},{"_id":{"source":"2019-03-23","status":false},"count":3},{"_id":{"source":"2019-03-08","status":false},"count":1},{"_id":{"source":"2019-02-02","status":true},"count":1},{"_id":{"source":"2019-02-02","status":false},"count":2},{"_id":{"source":"2019-01-29","status":false},"count":1}];
let {Arrayforstatusfalse,Arrayforstatustrue} = Object.entries(array.reduce((c, v) => {
c.Arrayforstatustrue[v._id.source] = c.Arrayforstatustrue[v._id.source] || 0;
c.Arrayforstatusfalse[v._id.source] = c.Arrayforstatusfalse[v._id.source] || 0;
if (v._id.status) c.Arrayforstatustrue[v._id.source] += v.count;
else c.Arrayforstatusfalse[v._id.source] += v.count;
return c;
}, {Arrayforstatusfalse: {},Arrayforstatustrue: {}}))
.reduce((c, [k, o]) => Object.assign(c, {[k]: Object.values(o)}), {});
console.log(Arrayforstatusfalse);
console.log(Arrayforstatustrue);
This?
const data = [
{"_id":{"source":"2019-04-06","status":false},"count":1},
{"_id":{"source":"2019-04-06","status":true},"count":1},
{"_id":{"source":"2019-03-24","status":false},"count":2},
{"_id":{"source":"2019-03-24","status":true},"count":1},
{"_id":{"source":"2019-03-23","status":false},"count":3},
{"_id":{"source":"2019-03-08","status":false},"count":1},
{"_id":{"source":"2019-02-02","status":true},"count":1},
{"_id":{"source":"2019-02-02","status":false},"count":2},
{"_id":{"source":"2019-01-29","status":false},"count":1},
];
const byDate = {};
data.forEach((f, ndx) => {
byDate[f._id.source] = byDate[f._id.source] || [];
byDate[f._id.source].push(f);
});
function mapCounts(byDate, status) {
return Object.values(byDate).map(d => {
const ndx = d.findIndex(e => e._id.status === status);
return ndx >= 0 ? d[ndx].count : 0;
});
}
const falseForDate = mapCounts(byDate, false);
const trueForDate = mapCounts(byDate, true);
console.log(falseForDate.join(','));
console.log(trueForDate.join(','));
note I'm curious what this is acutally for. The code above will not handle things if there are 3 of the same date because then there are would either be 2 counts for true or 2 for false. Which count to use. Similarly the same sitatuion arrises if their are 2 trues or 2 falses for the same date (same issue really). Maybe you want to sum the counts for true or false by date?
In that case
const data = [
{"_id":{"source":"2019-04-06","status":false},"count":1},
{"_id":{"source":"2019-04-06","status":true},"count":1},
{"_id":{"source":"2019-03-24","status":false},"count":2},
{"_id":{"source":"2019-03-24","status":true},"count":1},
{"_id":{"source":"2019-03-23","status":false},"count":3},
{"_id":{"source":"2019-03-08","status":false},"count":1},
{"_id":{"source":"2019-02-02","status":true},"count":1},
{"_id":{"source":"2019-02-02","status":false},"count":2},
{"_id":{"source":"2019-01-29","status":false},"count":1},
];
const byDate = {};
data.forEach((f, ndx) => {
byDate[f._id.source] = byDate[f._id.source] || [];
byDate[f._id.source].push(f);
});
function mapCounts(byDate, status) {
return Object.values(byDate).map(d => {
return d.reduce((acc, e) => acc + (e._id.status === status ? e.count : 0), 0);
});
}
const falseForDate = mapCounts(byDate, false);
const trueForDate = mapCounts(byDate, true);
console.log(falseForDate.join(','));
console.log(trueForDate.join(','));
or
const data = [
{"_id":{"source":"2019-04-06","status":false},"count":1},
{"_id":{"source":"2019-04-06","status":true},"count":1},
{"_id":{"source":"2019-03-24","status":false},"count":2},
{"_id":{"source":"2019-03-24","status":true},"count":1},
{"_id":{"source":"2019-03-23","status":false},"count":3},
{"_id":{"source":"2019-03-08","status":false},"count":1},
{"_id":{"source":"2019-02-02","status":true},"count":1},
{"_id":{"source":"2019-02-02","status":false},"count":2},
{"_id":{"source":"2019-01-29","status":false},"count":1},
];
const byDate = {};
data.forEach((f, ndx) => {
byDate[f._id.source] = byDate[f._id.source] || [0, 0];
byDate[f._id.source][f._id.status === true ? 1 : 0] += f.count;
});
const falseForDate = Object.values(byDate).map(v => v[0]);
const trueForDate = Object.values(byDate).map(v => v[1]);
console.log(falseForDate.join(','));
console.log(trueForDate.join(','));
You can use map to achieve this. They key of the map will be the source and value will be count. If no value found for a particular key, then assign 0. Otherwise assign value based on the given condition.
Iterate over all elements of inputArray. After the end of iteration, you will get two objects. Just take the values of the objects using Object.values() function.
You're done!!!
I have used ternary operator to make the code look short and easy. See the snippet below
var inputArray = [{"_id":{"source":"2019-04-06","status":false},"count":1},{"_id":{"source":"2019-04-06","status":true},"count":1},{"_id":{"source":"2019-03-24","status":false},"count":2},{"_id":{"source":"2019-03-24","status":true},"count":1},{"_id":{"source":"2019-03-23","status":false},"count":3},{"_id":{"source":"2019-03-08","status":false},"count":1},{"_id":{"source":"2019-02-02","status":true},"count":1},{"_id":{"source":"2019-02-02","status":false},"count":2},{"_id":{"source":"2019-01-29","status":false},"count":1}];
var trueObjects = {},
falseObjects = {};
inputArray.forEach(function(elem) {
var index = elem._id.source,
status = elem._id.status,
count = elem.count;
//initialize value for new index
trueObjects[index] = trueObjects[index] ? trueObjects[index] : 0;
falseObjects[index] = falseObjects[index] ? falseObjects[index] : 0;
//set value based on condition
trueObjects[index] = status ? count : trueObjects[index];
falseObjects[index] = !status ? count : falseObjects[index];
});
trueArray = Object.values(trueObjects);
falseArray = Object.values(falseObjects);
console.log(falseArray);
console.log(trueArray);
You can get unique sources (dates) and create true and false arrays for each source :
const dataArray = [{"_id":{"source":"2019-04-06","status":false},"count":1},
{"_id":{"source":"2019-04-06","status":true},"count":1},
{"_id":{"source":"2019-03-24","status":false},"count":2},
{"_id":{"source":"2019-03-24","status":true},"count":1},
{"_id":{"source":"2019-03-23","status":false},"count":3},
{"_id":{"source":"2019-03-08","status":false},"count":1},
{"_id":{"source":"2019-02-02","status":true},"count":1},
{"_id":{"source":"2019-02-02","status":false},"count":2},
{"_id":{"source":"2019-01-29","status":false},"count":1}];
// Get all sources
const sources = dataArray.map(item => item._id.source);
// Get unique sources
const uniqueSources = [...(new Set(sources))];
const arrayForStatusTrue = [];
const arrayForStatusFalse = [];
uniqueSources.forEach(source => {
// Check if source with status true exists
const itemWithStatusTrue = dataArray.find(item => (item._id.status && item._id.source === source));
itemWithStatusTrue ? arrayForStatusTrue.push(itemWithStatusTrue.count) : arrayForStatusTrue.push(0);
// Check if source with status false exists
const itemWithStatusFalse = dataArray.find(item => (!item._id.status && item._id.source === source));
itemWithStatusFalse ? arrayForStatusFalse.push(itemWithStatusFalse.count) : arrayForStatusFalse.push(0);
});
console.log(arrayForStatusTrue);
console.log(arrayForStatusFalse);
I would suggest using a Map to create one entry per date (source), which each would have two values representing the counts for both possible statuses (initialised with zero).
Then add the actual counts to those entries, and finally extract the data into the two arrays you expect:
// Sample input
const array = [{ _id: { source: "2019-04-06", status: false }, count: 1 }, { _id: { source: "2019-04-06", status: true }, count: 1 }, { _id: { source: "2019-03-24", status: false }, count: 2 }, { _id: { source: "2019-03-24", status: true }, count: 1 }, { _id: { source: "2019-03-23", status: false }, count: 3 }, { _id: { source: "2019-03-08", status: false }, count: 1 }, { _id: { source: "2019-02-02", status: true }, count: 1 }, { _id: { source: "2019-02-02", status: false }, count: 2 }, { _id: { source: "2019-01-29", status: false }, count: 1 }];
// Algorithm
const map = new Map(array.map(o => [o._id.source, [0,0]]));
array.forEach(o => map.get(o._id.source)[+o._id.status] += o.count);
const [noes, ayes] = [0, 1].map(i => Array.from(map.values(), a => a[i]));
// Output
console.log(JSON.stringify(noes), JSON.stringify(ayes));

Checking Multiple Items with a Map Function

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

return non array in using map

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)

Categories

Resources