I am doing file selection and push the data into an array but if the selected data has already exist in the array I want to remove it.
I am pushing my data :
_setSelectedFile(file_uri, file_key){
let selectedFiles = [...this.state.selectedFiles];
selectedFiles.push({ file_uri: file_uri, file_key: file_key });
this.setState({ selectedFiles });
}
The output of my array is something like this :
[
{
file_uri: "ph://9F983DBA-EC35-42B8-8773-B597CF782EDD/L0/001",
file_key: "2"
},
{
file_uri: "ph://CC95F08C-88C3-4012-9D6D-64A413D254B3/L0/001",
file_key: "5"
}
]
I stored the file_key as a reference when removing it later. I saw this answer Delete item from state array in react but not sure how to apply it since the question from the discussion is referring to one-dimensional array.
I tried out some trick and apparently it's working in my case. Hope this helps others too.
_setSelectedFile(file_uri, file_key){
var isExist = false;
var selectedFileKey = null;
let selectedFiles = [...this.state.selectedFiles];
if(this.state.selectedFiles != null){
this.state.selectedFiles.map((data, i)=>{
if(data.file_key === file_key){
isExist = true;
selectedFileKey = i;
}
})
}
if(isExist == true){
selectedFiles.splice(selectedFileKey, 1);
this.setState({selectedFiles: selectedFiles});
} else {
selectedFiles.push({ file_uri: file_uri, file_key: file_key });
this.setState({ selectedFiles });
}
}
So I do mapping and check if the data is already exist then assign isExist = true and store the key value selectedFileKey = i.
With isExist set as true I can proceed with removing the data from my array.
Related
I wants to prevent addition of duplicate items to cart. I have tried the code below but it's working only for single item, when there are multiple items in the cart the duplicate items are allowed to add in to the cart. Here is my code
addToCart = (id) => {
let item = this.getItem(id);
if ([...this.state.cart]) {
[...this.state.cart].map((i) => {
if (i.product_name == item.product_name) {
alert("Item is already in cart");
} else {
this.setState((this.state.cart = [...this.state.cart, item]));
}
});
} else {
this.setState((this.state.cart = [...this.state.cart, item]));
}
console.log(this.state.cart);
};
You need to use map only to check if the item already exists, and then either add it or alert that the item is repeated.
One way of doing it would be like this:
existing = [...this.state.cart].map((i) => {
if (i.product_name == item.product_name) {
return i;
}
});
if (existing) {
alert("Item is already in cart");
} else {
this.setState((this.state.cart = [...this.state.cart, item]));
}
Explanation
map function executes the code for each of the items in the collection, which means the moment it finds an item in the cart different from the item selected, it will add the item selected.
So let's say your cart has [apple, orange] and you want to add apple again. When the map code executes it first looks like this:
if ("apple" == "apple") {
alert("Item is already in cart");
} else {
this.setState((this.state.cart = [...this.state.cart, apple]));
}
It doesn't add the item because it already exists... but then it executes a second time, and it looks like this:
if ("orange" == "apple") {
alert("Item is already in cart");
} else {
this.setState((this.state.cart = [...this.state.cart, apple]));
}
It gets added because the second item is different.
What the new code does is that it returns a value only if the item exists and, after looping throuhght all the items in the cart, it checks that value and adds the item if it is nothing.
An item should be added to the cart, if the latter doesn't contain it already.
To check if an Array contains an object, that fulfills a certain condition use the some method, as said by #Isaac Batista.
On the other hand, when you want to update state, by using it's previous value, you should use the callback argument of setState.
See https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
this.setState((state)=>{
// if cart already contains item
if(state.cart.some(itm=>itm.product_name == item.product_name)) {
return {}; // do not update state
} else {
return {cart: state.cart.concat(item)}; // add item to cart
}
}
You can use filter method to check whether the item is already available or not. With this you can also avoid the nested if condition also.
addToCart = (id) => {
let item = this.getItem(id);
let checkCart = [...this.state.cart].filter((i) => {
return i.product_name == item.product_name;
});
if (checkCart.length !== 0) {
alert("Item is already in cart");
} else {
this.setState((this.state.cart = [...this.state.cart, item]));
}
console.log(this.state.cart);
};
Here is a functional exemple, but note some points:
You are mutating state, and you should not do it, as it is explained here. So, you should just call setState passing the new value via argument, like this: this.setState(newValue).
A map is used to create a new array, the correct function to find out if some element passes a rule is some. This will allow you to check if some product inside cart is the clicked product.
// quick example
[1,2,3,4].some(number => number === 2) // true
[1,2,3,4].some(number => number === 5) // false
Finally, i would do something like this
const { cart } = this.state;
const product = this.getItem(id);
// returns true if there is any product with the same id
const isProductInCart = cart.some((item) => item.id === product.id);
if (isProductInCart) {
alert("Product already in cart");
} else {
this.setState({
cart: [...cart, product]
});
}
Within each element in an array, there may or may not be a value that I need to grab. If the value is not in one element, I want to go to the next element to look for it. I'd like to know how to write the statement to do that in my Postman test. I already know how to get the values when they exist, but I want to go through each element until I find what I'm looking for to put in the variable.
I've googled how to write the code, but I'm new to this and I'm having trouble.
var jsonData = JSON.parse(responseBody);
postman.setGlobalVariable("Date", jsonData.array[0].field[1]);
if (postman.setGlobalVariable("Date", jsonData.array[0].field[1]) === ???
else (postman.setGlobalVariable("Date", jsonData.array[1].field[1]);)
Hi, Here is a sample response (thanks!): You can see the first element does not have the value, "NeedTheseDates" that I need to grab, but the second element does.
"SampleArray": [
{
"Date": "2019-05-18T00:00:00.0000000-04:00",
"NeedTheseDates": [],
"Anything": "data",
"OnlyDate": "2019-06-03T00:00:00.0000000-04:00"
},
{
"Date": "2019-06-16T00:00:00.0000000-04:00",
"NeedTheseDates": [
"2019-07-02T00:00:00.0000000-04:00",
"2019-07-03T00:00:00.0000000-04:00",
"2019-07-04T00:00:00.0000000-04:00",
"2019-07-05T00:00:00.0000000-04:00",
"2019-07-06T00:00:00.0000000-04:00",
"2019-07-07T00:00:00.0000000-04:00",
"2019-07-08T00:00:00.0000000-04:00",
"2019-07-09T00:00:00.0000000-04:00",
"2019-07-10T00:00:00.0000000-04:00",
"2019-07-11T00:00:00.0000000-04:00",
"2019-07-12T00:00:00.0000000-04:00"
],
Not very sure about the problem statement. So trying all combinations
If there are only two cases where the value could be (index 0 or 1)
let someDate = jsonData.array[0].field[1] === '???' ?
jsonData.array[0].field[1] : jsonData.array[1].field[1];
postman.setGlobalVariable('Date', someDate);
If the length of array is dynamic but the date you are looking for in field is always at index 1
let someDate;
jsonData.array.forEach((element) => {
element.field[1] === '???' && (someDate = element.field[1]);
});
postman.setGlobalVariable('Date', someDate);
This will traverse all the items irrespective of whether it finds the correct element before. You can use some to stop that
let someDate;
jsonData.array.some((element) => {
if (element.field[1] === '???') {
someDate = element.field[1]);
return true; // this will stop the loop
}
});
postman.setGlobalVariable('Date', someDate);
If the length of array is dynamic and field is also dynamic
let someDate;
jsonData.array.some((element) => {
element.field.some((oneDate) => {
if (oneDate === '???') {
someDate = oneDate;
return true; // this will stop the inner loop
}
});
if (someDate) {
return true; // this will stop the outer loop
}
});
postman.setGlobalVariable('Date', someDate);
I have a json array object $scope.products= []; and ng-click function called
addRow.
I want to perform a check before push new row to array is new row is already exists in array, or not when addRow function is called.
If it already exists, then new row is not push to array.
$scope.addRow = function(){
$scope.products.push({'pro_name':$scope.pro_name,'pro_id':$scope.pro_id, 'batch_no': $scope.input_batch_no });
}
Since you have a unique identifier you can check whether the list of added rows includes such element with this identifier.
$scope.addRow = function(product) {
if($scope.selectedProducts.find(p => p.pro_id === product.pro_id)) {
return;
};
$scope.selectedProducts.push(product);
}
Here's a working piece of code
Just Check if it exists already in the array:
$scope.addRow = function(){
var exists = false;
$scope.products.forEach(product => {
if (product.pro_name === $scope.pro_name && product.pro_id === $scope.pro_id && product.batch_no === $scope.batch_no) {
exists = true;
}
})
if (!exists) {
$scope.products.push({
'pro_name':$scope.pro_name,
'pro_id':$scope.pro_id,
'batch_no': $scope.input_batch_no
});
}
}
I'm trying to filter a JSON array using another JSON array criteria that I have using (filter).
Here is my code:
function filterArray(object, criteria){
return object.filter(function(obj){
for(var i=0;i<criteria.length;i++){
let criteriaEle = criteria[i];
return Object.keys(criteriaEle).forEach(function(key){
if(obj[key] == criteriaEle[key]){
return obj;
}
})
}
})
}
For example:
object = [{type:1,company:1,color:0,name:a},{type:2,company:1,color:0,name:b},{type:1,company:3,color:0,name:c},{type:4,company:1,color:0,name:d},{type:1,company:1,color:1,name:e}]
criteria = [{type:1,company:1,color:0},{type:1,company:1,color:1}]
So if I give these two arrays to the function it should return
obj = [{{type:1,company:1,color:0,name:a},{type:1,company:1,color:1,name:e}}]
I'm not sure where am I going wrong in this. Please help.
Update:
Also, I do not want to use obj.type or obj.company or object.color as parameters to search as I want to make my code maintainable and do not want to come and update it later if in future more criteria's are added.
const data = [{type:1,company:1,color:0,name:'a'},{type:2,company:1,color:0,name:'b'},{type:1,company:3,color:0,name:'c'},{type:4,company:1,color:0,name:'d'},{type:1,company:1,color:1,name:'e'}];
const criteria = [{type:1,company:1,color:0},{type:1,company:1,color:1}];
function checkCriteria(obj) {
return criteria.some(criterion => {
for (const key in criterion) {
if (criterion[key] !== obj[key]) {
return false;
}
}
return true;
});
}
const filtered = data.filter(checkCriteria);
console.log('Filtered array: ', filtered);
Here is one solution.
Here are some references
Array.some
Array.filter
Based on the comment, adding another snippet to explain the concept of closures.
const data = [{type:1,company:1,color:0,name:'a'},{type:2,company:1,color:0,name:'b'},{type:1,company:3,color:0,name:'c'},{type:4,company:1,color:0,name:'d'},{type:1,company:1,color:1,name:'e'}];
function createCriteriaValidationFunction(criteria) {
return function checkCriteria(obj) {
return criteria.some(criterion => {
for (const key in criterion) {
if (criterion[key] !== obj[key]) {
return false;
}
}
return true;
});
}
}
const criteria = [{type:1,company:1,color:0},{type:1,company:1,color:1}];
const filtered = data.filter(createCriteriaValidationFunction(criteria));
console.log('Filtered array: ', filtered);
It's the same concept as before, however, criteria was defined in the file. This time, criteria can be defined outside and can be passed in to the function. The trick is to create the checkCriteria function on the fly with criteria passed in and available in the closure. In both cases, criteria variable is available in the scope in which checkCriteria is executed.
getInitialState: function() {
p:{'Keeper' : [] , 'Defenders': [] , 'Midfield' : [], 'Forwards' : []}}
}
onUpdatePlayers : function (newState) {
var pos;
if (newState.position.includes('Back')) {
pos = 'Defenders'
} else if (newState.position.includes('Midfield')){
pos = 'Midfield'
} else if (newState.position.includes('Forward')) {
pos = 'Forwards'
} else {
pos = newState.position;
}
this.state.p[pos].push(newState)
}
Basically , I want to push some arrays into multiple state's property.
Somehow, I need to change this code "this.state.p[pos].push(newState)" to using this.setState. I've google it and found something like
this.setState({
p : this.state.p[pos].concat([newState])
});
Obviously, It does not help at all. Can you please advise me on this ?
It will be Big Thanks,
Cheers!!
If you do really need your state to be deeply nested you'll need to replace entire p property with new object. For example using Object.assign
this.setState({
p: Object.assign(this.state.p, {
[pos]: this.state.p[pos].concat(newState)
})
})
Danny Kim, you are missing quotes on the new key you wanted to add. Change your last line to
this.state.p['pos'].push(newState)