remove object from JSON array by id after delete from DB - javascript

I have a json array that looks like:
var ad =[{"itemID":"195","issue":"first","buttonText":"First","date":1481200571","link":"https://example.com/link"},{"itemID":"197","issue":"other","buttonText":"Something Else","date":1481200571","link":"https://example.com/linkother"},{"itemID":"215","issue":"main","buttonText":"Important","date":1481200571","link":"https://example.com/linkmain"}];
(The above example has 3 objects, but in reality it could have many more.)
And I have an ajax action on my page that will delete the row from the db that one of these objects represents. Rather than refresh my page with the entire json which is many rows and a db call, I would like to just permanently remove the object that is represented by itemID from the array in my page using javascript.

There are many ways of doing it.
The ones that come to my mind:
filtering out an item:
ad = ad.filter(item => item.itemId != 'DELETED ID');
finding index of an item and removing it
var deletedItem = ad.find(item => item.itemId == 'DELETED ID');
ad.splice(ad.indexOf(deletedItem), 1);

Related

Compare two arrays values, and populate if no match

I need help with matching two arrays. I have TypeScript in the example code, but it can be understood since its about array operations more or less.
In short:
I have two arrays; myItems[] and allItems[]. myItems[] can only hold maximum 4 values.
I want to first check if the items in myItems[] is 4, AND/OR exist in the other array allItems[].
If NOT: populate myItems[] with values from allItems[] (until it contains 4 values) and/or replace the items that is missing (relative to allItems[]) with other items in allItems[] (I'm trying to use default values instead of randomly taking values in my example code).
Description:
I have a widgets (quick links) module that show 4 links at a time, but there are in total 20 different links (or more). All links is stored in a list and each has its own unique ID. In code, all links is extracted and returned in an array (like the allItems[] in above example).
The user can save the links he/she wants to show in the widget. The user settings is stored and returned as an array with the ID of the links that the user have saved. Like the myItems[] above,
Problem:
I have a solution that check the length of the myItems[], and if needed populates items from the allItems[] one. However, it does NOT check if the items in the user array exist in allItems[] and then populates it with the default links. In practical it means that the user can save links and it will be shown in the widget as intended. BUT if a link is removed in the list (which will then be removed in the allItems array) only 3 items will be shown as the myItems[] doesn't check with the allItems[] array to see if it exists there.
Code:
public async getUserWidgets(): Promise<Widget[]> {
let allWidgets = await this.getAllWidgets(); //Array with all the links ID from the list
let userRepository = new UserProfileRepository(this.absoluteWebUrl);
let userSettings = await
userRepository.getUserExtensionValues(this.context); //Extracting the user Settings which contains the ID of the saved linksvar
result:Widget[] = []; //the array where the result will go in
//if the user doesnt have any saved links, or if the user have less than 4 saved links
if (userSettings == null || userSettings.QuickLinksWidgets == null ||
userSettings.QuickLinksWidgets.length < 4)
{result = allWidgets.filter((w) => {return w.defaultWidget;}).slice(0,4);
}
else {var ids =userSettings.QuickLinksWidgets;
for (let i = 0; i < 4; i++) {
let id = '' + ids[i];let w = allWidgets.filter((e) => { return e.id == id;});
if (w.length == 0) {
continue;}
result.push(w[0]);}}
return new Promise<Widget[]>(async (resolve) => {resolve(result);});}
A simple way to check if an array holds a value is using the includes() method.
for(let value of myitems){
if(allitems.includes(value)){
console.log("Duplicate")
}
}
The above code will loop through each value in your myitems array and test if that value is in the allitems array.

Array filter method to match IDs and check properties exist

I'm currently using a method to try to filter some arrays, the method is almost working but I can't seem to access the exact values -
I make a call and add each returned array into a bigger array, these arrays will then be assigned a productId and maybe some data, i am appending the productIds using this:
data.push({'productId': product.id});
Which unfortunately adds a new object to the array which means my function below doesnt work unless the productId is in the first object of each array:
let matchedArray = data.flatMap(arr => arr.filter(obj => obj.productId == id))
What I need to do is filter the array down to the subarray that matches the productId and ID and also that has some of the fields of data such as 'name' - so it checks that the name isnt empty.
The data set looks like this (array of subarrays)
id = 12345
data = [[],[],[],[],[],[],[],[],[{"id":"123","name":"africa soul
2019","startDate":null,"endDate":null,"country":null,"city":null,"type":"Ev
ent","members":null},{"productId":"12345"}],[],[],[],[],[],[],
[],[],[],[],[]]
As you can see the productId is appended to the array but isnt now working with my filter method, i need to filter for the right array that has matching ID's and at least one of the fields are also existing. I either need to change the way the productId is manually appended, or change the filter method?
Thanks so much if you can help
If you want to filter all the arrays which have some object which have a productId equal to a given value:
let data = [[],[],[],[],[],[],[],[],[{"id":"123","name":"africa soul 2019","startDate":null,"endDate":null,"country":null,"city":null,"type":"Event","members":null},{"productId":"12345"}],[],[],[],[],[],[],[],[],[],[],[]],
id = "12345";
let filtered = data.filter(arr => arr.some(a => a.productId === id))
console.log(filtered)
If you want to get the first match, use find instead of filter

Compare 2 immutable lists for equality

Im looking to do something that I would have thought was done so many times with Immutable.js Lists already but i can't seem to find this case. I have 2 lists. One with Items. And one that contains keys of the items selected as data. users who have selected things from items basically. I am storing the key from items as data in the profile of the user that selected the item (in a firebase db, not that it matters). So I want to simply filter the items in my app using a selector. In the selector Im looking to compare the key from items with the key I stored in the users profile.
If it's a match, then give me the matching data from items as state to use. I believe this should be a filter on Items of some kind?? To do the compare i also need to get the stored key data in the users profile to compare which is also a immutable list.
Im trying
const selectedItems = items.filter(
item => {
userItems.forEach(userItem => {
if (userItem.itemKey === item.key) {
return item <-------pretty sure this is where Im doing it wrong
}
})
});
If i hard code a record from my users profile and filter, I get what I expect which is new filtered list with one item matching the id below.
const selectedItems = items.filter(
item => {
return item.get('key') === '-LDR5cNZPjthN6nK9tzJ'
});
filter will create a new array with every element in the original array that returned a truthy value. With this in mind you could use a combination of filter and some to filter out all the objects you have a key for in userItems:
const selectedItems = items.filter(item =>
userItems.some(userItem => userItem.itemKey === item.itemKey)
);

Trying to dynamically organize JSON object elements into different arrays based on values

This is the JSON I'm working with:
https://data.cityofnewyork.us/resource/xx67-kt59.json?$where=camis%20=%2230112340%22
I'd be dynamically making the queries using different data, so it'll possibly change.
What I'm essentially trying to do is to somehow organize the elements within this array into different arrays based on inspection_date.
So for each unique inspection_date value, those respective inspections would be put into its own collection.
If I knew the dates beforehand, I could easily iterate through each element and just push into an array.
Is there a way to dynamically create the arrays?
My end goal is to be able to display each group of inspections (based on inspection date) using Angular 5 on a webpage. I already have the site up and working and all of the requests being made.
So, I'm trying to eventually get to something like this. But of course, using whatever dates in the response from the request.
2016-10-03T00:00:00
List the inspections
2016-04-30T00:00:00
List the inspections
2016-04-12T00:00:00
List the inspections
Just for reference, here's the code I'm using:
ngOnInit() {
this.route.params.subscribe(params => {
this.title = +params['camis']; // (+) converts string 'id' to a number
this.q.getInpectionsPerCamis(this.title).subscribe((res) => {
this.inspectionList = res;
console.log(res);
});
// In a real app: dispatch action to load the details here.
});
}
I wish I could give you more info, but at this point, I'm just trying to get started.
I wrote this in jQuery just because it was faster for me, but it should translate fairly well to Angular (I just don't want to fiddle with an angular app right now)
Let me know if you have any questions.
$(function() {
let byDateObj = {};
$.ajax({
url: 'https://data.cityofnewyork.us/resource/xx67-kt59.json?$where=camis%20=%2230112340%22'
}).then(function(data) {
//probably do a check to make sure the data is an array, im gonna skip that
byDateObj = data.reduce(function(cum, cur) {
if (!cum.hasOwnProperty(cur.inspection_date)) cum[cur.inspection_date] = [];
//if the cumulative array doesn't have the inspection property already, add it as an empty array
cum[cur.inspection_date].push(cur);
//push to inspection_date array.
return cum;
//return cumulatie object
}, byDateObj);
//start with an empty object by default;
console.log(byDateObj);
}, console.error);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Fastest way to add to and get values from a list of objects

I'm just getting started with JavaScript objects. I'm trying to store catalog inventory by id and locations. I think a single object would look something like this:
var item = {
id: number,
locations: ["location1", "location2"]
};
I've started to read a bit about it but am still trying to wrap my head around it. Not sure what is the fastest way add new items to a list with a location, add a new location to an existing item, all while checking for dupes. Performance of getting the locations later isn't as critical. This is part of a process that is running thousands of checks to eventually get items by id and location, so performance is key.
Final question, I'm not even sure if it's possible to store this in local storage. From another similar question, I'm not sure.
Using lodash, something like this should work to determine if an item id exists and append either a new item to the array, or just add a new location:
var item = [{
id: 1,
locations: ["location1", "location2"]
},{
id: 2,
locations: ["location2", "location4"]
}];
function findItem(id){
return _.findIndex(item, function(chr) {
return chr.id == id;
});
}
function addItem(id,locations) {
var position = findItem(id);
if (position<0) {
item.push({
id: id,
locations: locations
})
} else {
item[position].locations = _.uniq(item[position].locations.concat(locations));
}
}
addItem(2,['location292']);
addItem(3,['location23']);
console.log(item);
What it basically does is to search the array of objects (item) for an id as the one we are passing to the addItem() function, if it is found we add the new locations array to the existing item, if not it's creating a new object with a new id and location.
You've asked a question that contains some tradeoffs:
The simplest and fastest way to retrieve a list of locations is to store them in an array.
The fastest way to check something for a duplicates is not an array, but rather a map object that maintains an index of the key.
So, you'd have to discuss more about which set of tradeoffs you want. Do you want to optimize for performance of adding a non-duplicate or optimize for performance of retrieving the list of locations. Pick one or the other.
As for localStorage, you can store any string in LocalStorage and you can convert simply non-reference objects to a string with JSON.stringify(), so yes this type of structure can be stored in LocalStorage.
For example, if you want to use the array for optimized retrieval, then you can check for duplicates like this before adding:
function addLocation(item, newLocation) {
if (item.locations.indexOf(newLocation) === -1) {
item.locations.push(newLocation);
}
}
Also, you can store an array of items in LocalStorage like this:
localStorage.setItem("someKey", JSON.stringify(arrayOfItems));
And, then some time later, you can retrieve it like this:
var arrayOfItems = JSON.parse(localStorage.getItem("someKey"));

Categories