Javascript array equality control - javascript

Hi I have two changeable length arrays and I tried If there is no value I want, delete it from that array
array1 = [
{
"serial": "3",
"code": "1"
},
{
"serial": "700",
"code": "1"
},
{
"serial": "300",
"code": "1"
},
{
"serial": "400",
"code": "1"
}
]
array2 = [{
"someting": 10,
"someting2": "20",
"serialList": ["700","711"],
},
{
"someting": 10,
"someting2": "30",
"serialList": ["300"],
},
{
"someting": 0,
"someting2": "0",
"serialList": [],
}
]
this my two array as I said arrays length is changeable sometimes array1 length big, sometimes array2 and I want If serial number in array1 does not exist in array2 delete from array1 element,
according to above array1[0] and array1[3] serial codes does not exist any element of array2 I want to output array1 is:
array1 = [
{
"serial": "700",
"code": "1"
},
{
"serial": "300",
"code": "1"
}
]
How can I do that, thnx

here is a simple and readable approach to achieve that
let allowedSerials = array2.map( obj=> obj.serialList ).flat();
let result = array1.filter( obj => allowedSerials.includes(obj.serial) )
check the snippet below:
let array1 = [
{
"serial": "3",
"code": "1"
},
{
"serial": "700",
"code": "1"
},
{
"serial": "300",
"code": "1"
},
{
"serial": "400",
"code": "1"
}
]
let array2 = [{
"someting": 10,
"someting2": "20",
"serialList": ["700","711"],
},
{
"someting": 10,
"someting2": "30",
"serialList": ["300"],
},
{
"someting": 0,
"someting2": "0",
"serialList": [],
}
];
// straight-forward solution:
let allowedSerials = array2.map( obj=> obj.serialList ).flat();
let result = array1.filter( obj => allowedSerials.includes(obj.serial) )
console.log(result);

Related

How can i filter result if i have array in body

i have a payload
{
"category": "Mobile",
"price": {
"from": "10",
"to": "50"
},
"location": [
"Jakrta",
"Bandung",
"Surabaya"
],
"rating": [
"1",
"2",
"3"
]
}
i want to find all object which have rating 1 or 2 or 3 and also have any location
Basically i am creating a filter for an ecommerce store i which we will get multiple location and multiple ratings as well so we will return only those object which have matched property. i am attaching a screenshot of UI for better understanding.
i want to run this filter with multiple location and multiple checked checkbox
You can do create a filter dynamically:
const { category, price, location, rating } = req.body;
const filter = {};
if (category) filter.category = category;
if (price) filter.price = { $gte: parseInt(price.from, 10), $lte: parseInt(price.to, 10) };
if (location?.length) filter.location = { $in: location };
if (rating?.length) filter.rating = { $in: rating };
const data = await Collection.find(filter);
If you want to filter your objects, you should use filter() from your array :
const arr = [{
"category": "Mobile1",
"price": {
"from": "10",
"to": "50"
},
"location": [
"Jakrta",
"Bandung",
"Surabaya"
],
"rating": [
"1",
"2",
"3"
]
},
{
"category": "Mobile2",
"price": {
"from": "10",
"to": "50"
},
"location": [
"Jakrta",
"Bandung",
"Surabaya"
],
"rating": [
"2",
"3"
]
}];
const result = arr.filter(el => el.rating.includes("1") || el.rating.includes("2") || el.rating.includes("3"));
console.log(result);

What is the proper way to match key and value from an array of objects and return a new object with only that key

I'm trying to make a function in javascript in order to match a key and an array of objects from an API. The matching is based on 2 parameters coming from an API.
A key which is a string and an array of objects with keys and values.
The output of this match should be a new array of objects with the values where that passed key is matching with the key of that array of objects passed as a parameter.
I prepared a sample of what I'm trying to achieve but is not working as I don't know how to do it properly and below it will be moe details about it
const criteriaJson = [{
"age": {
"min": "18",
"max": "65"
},
"pain": {
"min": "5"
},
"disease": {
"valid": [
"MDD",
"PTSD"
],
"invalid": [
"None"
]
},
"medicines": "true",
"bmi": {
"min": "25",
"max": "100"
},
"weight": "90",
"gender": [
"1",
"2",
"3"
],
"pressure": "100",
"smoker": "20",
"zip": "^w+s{1}w+$"
},
{
"age": {
"min": "16",
"max": "18"
},
"pain": {
"max": "10"
},
"bmi": {
"max": "85"
},
"disease": {
"valid": [
"none"
],
"invalid": [
"PTT",
"ADT",
"OLL"
]
},
"weight": "70",
"gender": [
"1"
],
"pressure": "10"
}
]
const question = {
key: "medicines"
}
// *Matching and extracting the right criteria data for the provided question key
// *inside the criteria object
// *returns an object with the right criteria
// *doing it for every group set of rules
function questionCriteriaKeyMatch(criteriaJson, question) {
criteriaJson.map((criteria) => {
return Object.keys(criteria)
.filter((key) => {
return key === question.key;
})
.reduce((cur, key) => {
return Object.assign(cur, {
criteria: criteria[key],
});
}, {});
});
}
console.log(questionCriteriaKeyMatch(criteriaJson, question));
To explain what data we are getting that criteriaJson
This data is an array of objects which contains a set of rules divided into objects for the same item but referring to a different group.
object 1 is criteria 1 and object 2 is criteria 2 to make it simple in this specific case.
[{
"age": {
"min": "18",
"max": "65"
},
"pain": {
"min": "5"
},
"disease": {
"valid": [
"MDD",
"PTSD"
],
"invalid": [
"None"
]
},
"medicines": "true",
"bmi": {
"min": "25",
"max": "100"
},
"weight": "90",
"gender": [
"1",
"2",
"3"
],
"pressure": "100",
"smoker": "20",
"zip": "^w+s{1}w+$"
},
{
"age": {
"min": "16",
"max": "18"
},
"pain": {
"max": "10"
},
"bmi": {
"max": "85"
},
"disease": {
"valid": [
"none"
],
"invalid": [
"PTT",
"ADT",
"OLL"
]
},
"weight": "70",
"gender": [
"1"
],
"pressure": "10"
}
]
However, the cases for this data are 3 essentially
the object is empty as no criteria exist in this case from API the match with the key which doesn't exist will output null
the array has one object only so the match needs to be done on this only object and if the key does not match output null
we have an array of more than one object in this case we need to match for every single object the key and if not match output is null.
Starting with the simple case when we receive an empty array of objects
const obj = [];
const key = 'someKey';
// Output as there is no matching
[null]
Example of the second case, when we have one object in the array
const obj = [{
"age": {
"min": "18",
"max": "65"
},
"pain": {
"min": "5"
},
"disease": {
"valid": [
"MDD",
"PTSD"
],
"invalid": [
"None"
]
},
}]
// Output matching key === age -> I'm open to suggestions how this output should be for // one obj only in the array
[{
criteria: { min:"18", max:"65" }
}]
// key === pain
[{
criteria: "5"
}]
// key === disease
[{
criteria: {valid: ["MDD","PTSD"], invalid: ["None"] }
}]
// key === notExistingKey means the key we are passing to match doesn't have a match so // we output null in this case
[{ null }]
From the above example, we output the matching values with the key passed as a param, when no match then is null
The last case is the more complex probably when we have an array of objects of the criteria and this should work for an array length > 1.
Using same data as in the snippet showing what is the expected output
const criteriaJson = [{
"age": {
"min": "18",
"max": "65"
},
"pain": {
"min": "5"
},
"disease": {
"valid": [
"MDD",
"PTSD"
],
"invalid": [
"None"
]
},
"medicines": "true",
"bmi": {
"min": "25",
"max": "100"
},
"weight": "90",
"gender": [
"1",
"2",
"3"
],
"pressure": "100",
"smoker": "20",
"zip": "^w+s{1}w+$"
},
{
"age": {
"min": "16",
"max": "18"
},
"pain": {
"max": "10"
},
"bmi": {
"max": "85"
},
"disease": {
"valid": [
"none"
],
"invalid": [
"PTT",
"ADT",
"OLL"
]
},
"weight": "70",
"gender": [
"1"
],
"pressure": "10"
}
]
const key = 'medicines'
// the output should be a new array of objects as we need to compare each object to find // the key match and output every single value
// key === medicines
[
{ criteria: 'true' }, -> we have a match in the first obj
{ criteria: null }, -> we have no match in the second obj
]
// key === age
[
{ criteria: { min: "18", max: "65" }}, -> we have a match in the first obj
{ criteria: { min: "16", max: "18" }}}, -> we have a match in the second obj
]
// For the rest of the keys should follow the same logic and with more objects, we have more
// objects in the output we have
I'm adding criteria as I need that in a second phase to be able to access that obj and extract the values for further use. As the keys are not the same always as are strings from API set in a client I need a way to facilitate access to the new object by assigning a hard-coded key. That is why when there is a match I just need the values and key like criteria, so I can access without an issue the values
I started with a reduce method as I thought maybe that was the way but in the end, I'm open to new solutions as cannot figure out how to achieve my goal.
The important note is that I cannot use for loops as I have strict rules of code style which cannot change.
If will be any comment with particular questions or request will try to explain better or update my question with more relevant info.
Seems like you just want to map the array to a new array with just the values. If the key does not exist, you would just set the criteria value to null, otherwise you set the criteria to whatever the property's value is.
const criteriaJson = [{
"age": {
"min": "18",
"max": "65"
},
"pain": {
"min": "5"
},
"disease": {
"valid": [
"MDD",
"PTSD"
],
"invalid": [
"None"
]
},
"medicines": "true",
"bmi": {
"min": "25",
"max": "100"
},
"weight": "90",
"gender": [
"1",
"2",
"3"
],
"pressure": "100",
"smoker": "20",
"zip": "^w+s{1}w+$"
},
{
"age": {
"min": "16",
"max": "18"
},
"pain": {
"max": "10"
},
"bmi": {
"max": "85"
},
"disease": {
"valid": [
"none"
],
"invalid": [
"PTT",
"ADT",
"OLL"
]
},
"weight": "70",
"gender": [
"1"
],
"pressure": "10"
}
]
function getCriteria (key, data) {
if (!data?.length) return [null]
return data.map(item => ({ criteria: item[key] || null }));
}
console.log('age', getCriteria('age', criteriaJson));
console.log('medicines', getCriteria('medicines', criteriaJson));
console.log('pressure', getCriteria('pressure', criteriaJson));

Update only after all the checks are passed

I want to update array of object only after all the checks are passed. I have array of object representing all the articles and other array of object all the available stock.
I want to check the if all the articles are in stock then only I want to update the stock array. Here is my code:
const articles = [{
"id": "1",
"quantity": "4"
}, {
"id": "2",
"quantity": "8"
}, {
"id": "4",
"quantity": "1"
}];
let stock = [
{
"id": "1",
"stock": "6"
},
{
"id": "2",
"stock": "6"
},
{
"id": "3",
"stock": "2"
},
{
"id": "4",
"stock": "2"
}
];
articles.map(article => {
stock.map(item => {
if(item.id === article.id){
if(article.quantity <= item.stock){
item.stock = item.stock - article.quantity;
} else {
console.log('error');
throw error;
}
}
});
});
Problem with this solution is that it updates stock for id = 1 even though id = 2 is not enough. I am trying to check if all the articles are in stock are in enough quantity and update(minus) them in stock array. So in this case code will update stock array like this:
stock = [
{
"id": "1",
"stock": "2"
},
{
"id": "2",
"stock": "6"
},
{
"id": "3",
"stock": "2"
},
{
"id": "4",
"stock": "2"
}
];
Can someone suggest how can I fix this?
You can use Array.prototype.find(). Note: The snippet assumes that all articles have an "id" property, it doesn't check for "art_id".
const articles = [{
"id": "1",
"quantity": "4"
}, {
"id": "2",
"quantity": "8"
}, {
"id": "4",
"quantity": "1"
}];
let stock = [{
"id": "1",
"stock": "6"
},
{
"id": "2",
"stock": "6"
},
{
"id": "3",
"stock": "2"
},
{
"id": "4",
"stock": "2"
}
];
// Use Array.prototype.some() to check for items that don't have enough stock
const haveEnough = !articles.some(article =>
// Turns "1" into 1
parseInt(
// Find the stock with the same id as the article
stock.find(stock => stock.id === article.id).stock
) <
parseInt(article.quantity))
console.log(haveEnough)
You can then update the stock in
if (haveEnough) {
// Do something
}
I am assuming that the art_id key in the articles array should be id.
Unfortunately you can't do it all in one loop and you will instead have to loop through all the articles first to find out if their stock is enough and then loop though them again to change the existing stock:
const articles = [
{
id: '1',
quantity: '4',
},
{
id: '2',
quantity: '5',
},
{
id: '4',
quantity: '1',
},
];
let stock = [
{
id: '1',
stock: '6',
},
{
id: '2',
stock: '6',
},
{
id: '3',
stock: '2',
},
{
id: '4',
stock: '2',
},
];
// Are there any articles that do not have enough stock
const outOfStockArticles = articles.find((article) => {
const articleStock = stock.find((stock) => stock.id === article.id);
return Number.parseInt(article.quantity) > Number.parseInt(articleStock.stock);
});
// If there are no out of stock articles - change existing stock values
if (!outOfStockArticles) {
articles.forEach((article) => {
const articleStock = stock.find((stock) => stock.id === article.id);
articleStock.stock = Number.parseInt(articleStock.stock) - Number.parseInt(article.quantity);
});
}
There is an inconsistency in your articles array, I suppose that every articles has an "art_id", and not some an "id" and some an "art_id".
You can simply find your article using the Array.prototype.find function, and then by the isAvailable function check that an article is present in the right quantity in the stock list.
Now you can use the Array.prototype.every function that do exactly what you want! It will return true only if every element of the array satisfy the condition, in our case the isAvailable function.
Here a simple fiddle:
const articles = [{
"art_id": "1",
"quantity": "4"
}, {
"art_id": "2",
"quantity": "8"
}, {
"art_id": "4",
"quantity": "1"
}];
const stock = [{
"id": "1",
"stock": "6"
},
{
"id": "2",
"stock": "6"
},
{
"id": "3",
"stock": "2"
},
{
"id": "4",
"stock": "2"
}
];
const isAvaiable = (article) => {
return stock.find(element => element.id === article.art_id).stock >= article.quantity;
}
if (articles.every(isAvaiable)) {
console.log("I can update")
} else {
console.log("I cannot update")
}

change the value of object inside a list

My code's output is like this:
let myArray = [{"num": "2", "name": "Jhon"}, {"num": "1", "name": "Sara"}, {"num": "2", "name": "Domnic"}, {"num": "3", "name": "Bravo"}]
How can I access value of num in each field of the list and if num: 2, change its value to 5?
Use Array.forEach to change the original Array
let myArray = [{ "num": "2", "name": "Jhon" }, { "num": "1", "name": "Sara" }, { "num": "2", "name": "Domnic" }, { "num": "3", "name": "Bravo" }]
myArray.forEach((node) => node.num = node.num == "2" ? "5" : node.num);
console.log(myArray);
If you want to create a new array from the existing one, Use Array.map
let myArray = [{ "num": "2", "name": "Jhon" }, { "num": "1", "name": "Sara" }, { "num": "2", "name": "Domnic" }, { "num": "3", "name": "Bravo" }]
const newArray = myArray.map(({ ...node }) => node.num = node.num == "2" ? "5" : node.num);
console.log(newArray);
Please Note: Do not forget to use spread syntax ({ ...node }) else your original array will be modified here.
You could use array map:
let myArray = [{
"num": "2",
"name": "Jhon"
}, {
"num": "1",
"name": "Sara"
}, {
"num": "2",
"name": "Domnic"
}, {
"num": "3",
"name": "Bravo"
}]
const result = myArray.map(({...item}) => {
if (item.num == 2)
item.num = "5"
return item
})
console.log(result)

how to group JSON objects from array of JSON objects?

Here is an array of JSON objects that has array values that I want to group by (pull unique):
let myArray = [
{
"_id": "1",
"subdata": [
{
"subid": "11",
"name": "A"
},
{
"subid": "12",
"name": "B"
}
]
},
{
"_id": "2",
"subdata": [
{
"subid": "12",
"name": "B"
},
{
"subid": "33",
"name": "E"
}
]
}
]
Finally I need to get:
[
{
"subid": "11",
"name": "A"
},
{
"subid": "12",
"name": "B"
},
{
"subid": "33",
"name": "E"
}
]
I've tried lodash with no success:
let newArray = lodash.uniqBy(lodash.concat(myArray, 'subdata.subid'), '_id');
Of course I can scan each array element one by one but thought there is easy way to do it with lodash
Use _.flatMap() to get the an array of all subdata items, and then use _.uniqueBy() with subid:
const myArray = [{"_id":"1","subdata":[{"subid":"11","name":"A"},{"subid":"12","name":"B"}]},{"_id":"2","subdata":[{"subid":"12","name":"B"},{"subid":"33","name":"E"}]}];
const result = _.uniqBy(_.flatMap(myArray, 'subdata'), 'subid');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
With lodash/fp you can generate a function using _.flow() with the same methods:
const fn = _.flow(
_.flatMap('subdata'),
_.uniqBy('subid')
);
const myArray = [{"_id":"1","subdata":[{"subid":"11","name":"A"},{"subid":"12","name":"B"}]},{"_id":"2","subdata":[{"subid":"12","name":"B"},{"subid":"33","name":"E"}]}];
const result = fn(myArray);
console.log(result);
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>

Categories

Resources