How do I save JavaScript variables permenantly/persistently? - javascript

I have 5 arrays, which can all be updated by the user. They are structured as:
var nameStore = [
{ name: "Tim Jones", idn: "i0001" },
{ name: "Mark Gooderham", idn: "i0002" }
];
var nameStoreName;
var subjectStore = [
{ name: "Sailing", ids: "s0001" },
{ name: "Navigation", ids: "s0002" }
];
var subjectStoreName;
var classStore = [
{ name: "Class A", idc: "c0001" },
{ name: "Class 2", idc: "c0002" }
];
var classStoreName;
var roomStore = [
{ name: "Room 1", idr: "r0001" },
{ name: "Room 2", idr: "r0002" }
];
var weekStore = [
{ week: 1, weekTimes: ["mon01i0001s0001c0001r0001", "mon02i0001s0002c0002r0002"] },
{ week: 2, weekTimes: ["mon02i0002s0002c0002r0002"] },
];
I want to be able to store these arrays permanently, so when the webpage closes, the arrays will have their data saved, and can then be accessed by another user later. I know this is a big question, but even if you could just direct me to other resources, that would help.
Thanks.

For that purpose, you should store your arrays in a database. Before closing page, submit arrays to DB and update records. When user opens the webpage, query DB and get arrays' contents.

You can use localStorage to store the array on the browser if you're not using database to persist.
localStorage.setItem('key', JSON.stringify(arr));
var item = JSON.parse(localStorage.getItem('key'));

Related

Functional Programming exercise I can't figure out

I've been looking at a problem for hours and failing to find a solution. I'm given an array of customer objects.
In each customer object is an array of friends.
In the array of friends is an object for each friend, containing some data, including a name key/value pair.
What I'm trying to solve for: I'm given this customers array and a customer's name. I need to create a function to find if this customer name is in any other customer's friend lists, and if so, return an array of those customer's names.
Below is a customer list. And as an example, one of the customers is Olga Newton. What the code should be doing is seeing that Olga Newton is a customer and is also in the friends lists of Regina and Jay, and should be returning an array of Regina and Jay.
I thought I could do this simply with a filter function, but because the friends list is an array with more objects, this is adding level of complexity for me I can't figure out.
Below is a customer array. The out put should be
['Regina', 'Jay']
and what I've gotten has either been
[{fullCustomerObj1}, {fullCustomerObj2}]
or
[ ]
What am I missing?
Here is the customer array:
var customers = [{
name: "Olga Newton",
age: 43,
balance: "$3,400",
friends: [{
id: 0,
name: "Justice Lara"
}, {
id: 1,
name: "Duke Patrick"
}, {
id: 2,
name: "Herring Hull"
}, {
id: 3,
name: "Johnnie Berg"
}]
}, {
name: "Regina",
age: 53,
balance: "$4,000",
friends: [{
id: 0,
name: "Cheryl Kent"
}, {
id: 1,
name: "Cynthia Wells"
}, {
id: 2,
name: "Gutierrez Waters"
}, {
id: 3,
name: "Olga Newton"
}]
}, {
name: "Jay",
age: 28,
balance: "$3,000",
friends: [{
id: 0,
name: "Cross Barnett"
}, {
id: 1,
name: "Raquel Haney"
}, {
id: 2,
name: "Olga Newton"
}, {
id: 3,
name: "Shelly Walton"
}]
}];
Use filter and map, please.
function friends(c, name){
return c.filter((a) => {
return a.friends.map(b => b.name).includes(name)
}).map(a => a.name);
}
console.log(friends(customers, "Olga Newton"));
// ['Regina', 'Jay']
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
We look to an array (friends[]) inside anther (customers[]), So used two for loops, the first determine witch customer will look for his friends, and the second the array will search inside, then set if statement if the cust name is inside friends[]: adding the customer name to customerFriends[] array, At the end return the customerFriends[].
let cust = "Olga Newton"; // Get the customer name who you look for his friends.
const findFriend = (cust, arrs) => { // Create findFriend function.
let customerFriends = []; // Create an array to set the result to it.
for (let i = 0; i < arrs.length; i++) { // For each Customer.
for (const arr of arrs[i].friends) { // For each Friend.
if (arr.name === cust) { // Use Strict equality to find Customer name in friends[].
customerFriends.push(arrs[i].name); // Add the customer name to the customerFriends[].
}
}
}
return customerFriends;// Return the final results.
}
console.log(findFriend(cust, customers)); // Call the function.

find and update property of nested object with lodash

I have been scanning through stackoverflow topics and couldn't find answer to the problem i am having.
What i need to do is to find object inside nested (2 depths) array by some of the values and then update other of its values. I managed to put together the finding and also setting seems to work, the problem is that lodash does return main object and it updates main object, not the nested one i actually need.
lets take this structure:
var data = [
{
name: 'I',
status: "0",
categories: [
{
name: 'I1',
status: "0",
specifics: [
{
name: "I1a",
status: "0",
}
]
}
]
}
];
i need to find object inside specifics by its name and then update its status.
so lets try simple find first:
var find = _.find(data, { categories: [ { specifics: [ { name: "I1a" } ] } ]});
this is working but it returns the object with name: I so first main one.
so then if i try to update with this:
var set = _.set(_.find(data, { categories: [ { specifics: [ { name: "I1a" } ] } ]}), 'status', "1");
It also does work but it updates status of I instead of what i was looking for which is I1a.
Is there a way to make finding and therefore setting to return / work on actually queried object ?
var data = [
{
name: 'I',
status: "0",
categories: [
{
name: 'I1',
status: "0",
specifics: [
{
name: "I1a",
status: "0",
}
]
}
]
}
];
var find = _.find(data, { categories: [ { specifics: [ { name: "I1a" } ] } ]})
console.log('find', find);
var set = _.set(_.find(data, { categories: [ { specifics: [ { name: "I1a" } ] } ]}), 'status', "1");
console.log('set', set);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

Creating an object from API data and adding it to an array dynamically

I have a data set that I'm pulling in from a database. It's one dimensional and I basically need to make it more structured. I refer to it as "flat".
I need to display a heading, and items under that heading that are related to the heading.
The data comes in as having and section_name (the heading) and item_name (items) and other data unique to each item like download URLs etc.
item_name(item)_______section_name(header)
first_________________Funds
second________________Funds
third_________________Funds
fourth________________Literature
fifth_________________Literature
sixth_________________Literature
seventh_______________Literature
eighth________________DueDilligence
I don't know what any of the names will be for the items or sections, or how many items, sections, or items per section. As I said, it's very flat. This needs to be fully dynamic which is why this is complicating things for me.
Here is what I've done.
API call to retrieve data. Store data in a state as an array (it comes in as an array of objects).
I create an empty array to store my newly structured data.
I loop through the data with a foreach.
I create a new object for my new data to add to the new array so I can loop over it later.
I first check to make sure the data exists.
To create the headers I check to see if my new empty array is actually empty OR my section_name is not the same as the last one.(in the original data array I got from the API call)
I store the section_names as an object in the new array (newArray.push(newObject)
I've gotten this far. Now I need to take the item_names that correlates to the section_names and store them in the object under each header name, or at least in the same index.
_generateInfo() {
let dataArray = this.state.stepTwoData
let newArray =[]
dataArray.forEach(function(item, index) {
let newObject = {}
if (index > 0) {
if (newArray.length === 0 || item.investor_portal_section_name !== dataArray[index -1].investor_portal_section_name) {
newObject["name"] = item.investor_portal_section_name
newObject["items"] = []
newArray.push(newObject)
}
})
console.log(newArray)
}
I tried pushing the items to the "number" array on my new object and that doesn't seem to work properly. Sometimes it will duplicate my newObject.name
Checking if the newObject.name === the section_names in the array and push it to the "number" array in my new object just creates new key-value pairs so it's still not correlating.
I tried looping through again in the if statement and if section_name === newObject.name then create a newObject and push it, but it would only push one of the items repeatedly instead of going through all of them.
I need to loop through and create a header (one header per different section_name). Then add each item that corresponds to the section_name to it. like this
[
{section_name(header): "Funds",
items: [
{
name: item_name,
sku: item_sku,
url: item_url
},
{
name: item_name,
sku: item_sku,
url: item_url
}]
},
{section_name(header):"Literature",
items: [
{name: item_name,
sku: item_sku,
url: item_url
},
{
name: item_name,
sku: item_sku,
url: item_url
}]}
]
Using associative array (dictionary) to segregate you data itmes by categories will do the job.
I've drafted some POC code that illustrates the idea. The key element there is buildAssociativeArray function
const raw_data = [
{item_name: "first", section_name: "Funds"},
{item_name: "second", section_name: "Funds"},
{item_name: "third", section_name: "Funds"},
{item_name: "fourth", section_name: "Literature"},
{item_name: "fifth", section_name: "Literature"},
{item_name: "sixth", section_name: "Literature"},
{item_name: "seventh", section_name: "Literature"},
{item_name: "eighth", section_name: "DueDilligence"},
]
function buildAssociativeArray(data) {
const dictionary = {};
for (var i = 0; i < data.length; i++) {
const item = data[i];
const section = item.section_name;
var dictEntry = dictionary[section];
if (!dictEntry) {
dictEntry = [];
dictionary[section] = dictEntry;
}
dictEntry.push({
name: item.item_name,
// other fields like sku: item_sku or url: item_url may follow here
});
}
return dictionary;
}
const dictionary = buildAssociativeArray(raw_data);
console.log(dictionary);
/*
At this point
dictionary == {
"Funds": [
{
"name": "first"
},
{
"name": "second"
},
{
"name": "third"
}
],
"Literature": [
{
"name": "fourth"
},
{
"name": "fifth"
},
{
"name": "sixth"
},
{
"name": "seventh"
}
],
"DueDilligence": [
{
"name": "eighth"
}
]
}
*/
// Associcative array dictionary itself allows to further solve you task using for (var key in dictionary) {...} operator
// If however you need to obtain the data structure looking exactly like the one in your question you may go further with following function
function transformAssociativeArray(dictionary) {
const array = [];
for (var key in dictionary) {
const items = dictionary[key];
const newEntry = {
section_name: key,
items: items,
}
array.push(newEntry);
}
return array;
}
const array = transformAssociativeArray(dictionary);
console.log(array);
/*
At this point
array == [
{
"section_name": "Funds",
"items": [
{
"name": "first"
},
{
"name": "second"
},
{
"name": "third"
}
]
},
{
"section_name": "Literature",
"items": [
{
"name": "fourth"
},
{
"name": "fifth"
},
{
"name": "sixth"
},
{
"name": "seventh"
}
]
},
{
"section_name": "DueDilligence",
"items": [
{
"name": "eighth"
}
]
}
]
*/

Filter objects based on a match in another array

I am trying to use Lodash to filter an array of objects based on a match of id's, this is what I have tried:
var team = _.find(this.teams, { 'id': this.newSchedule.team});
_.filter(this.yards, function(yard) {
return _.find(team.yards, { id: yard.id });
});
yards data:
[ { "id": 1, "name": "Test" },{ "id": 2, "name": "Test 2" } ]
team data:
[ { "id": 1, "name": "Team 1", "yards": [{ "id": 1, "name" }] ]
I want this.yards to show the yards based on the yard id from a selected team.
Its hard to understand what you mean, does the yard id match the team id?
If so it sounds like what you need to do is first find the team with the same id then grab that teams yards. Therefore I would use the map function twice:
const result = this
.yards
.map(y => team.find(t => t.id === y.id)) // join with the right team
.map(t => t.yards) // reduce to that teams yards
As team is an array, you need to iterate it before doing the _.find on an individual element in that array. It doesn't help that you called your variable team (singular). teams would make more sense.
Here is how you would change your lodash code:
var yards = [ { id: 1, name: "Test" },{ id: 2, name: "Test 2" } ],
teams = [ { id: 1, name: "Team 1", yards: [{ id: 1, name: "Missing string" }] } ]
result = _.filter(this.yards, function(yard) {
return _.some(this.teams, function(team) {
return _.find(team.yards, { id: yard.id });
});
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>
So this returns the yards that are related to at least one team.

JavaScript/jQuery DTOs/Objects to hold State

I'm usually a C# developer, but writing a mostly-client side application using jQuery.
It is reasonably straight forward: I have a list of "groups" which have some parameters (like a group name) and a list of "users" who also have some parameters.
At the moment I try to manage that using a <li> with a specific id, so there is a lot of string-matching involved to turn <li id="group-2">Name - ExtraInfo</li> back into something I can work with.
I feel that this approach is stupid because a) I use the UI as back-end for state and b) I rely on string parsing rather than working with real objects.
In C# I would just create a DTO (essentially a List<Group>), but I have not enough experience in JavaScript/jQuery to do that there.
Can someone give me some quick tips how to create a custom object and manage a list of these?
I'd just use arrays and objects (let's say JSON):
var groups = [
{
name: "Name",
info: "Extra"
},
{
name: "Name",
info: "Extra"
}
];
Regarding manipulation of the array. jQuery has some array utilities. For the question in your comment, you'd use grep:
var filteredGroups = groups.grep(function (group, i) {
return group.name == "What I'm interested in";
});
It's the equivalent of a Select().Where() in Linq (I'm not a .NET expert so there may be some things that don't match).
Anyway, that would be just the model part of an MVC structure. You still need some functions to map a collection of groups to a <ul> element. Then you'd have the view too.
Expanding on Ionut G. Stan's answer, I suggest nested objects:
var groups = {
group1: {
name: "Group 1",
users: {
uid1: { name: "User 1" },
uid2: { name: "User 2" },
uid3: { name: "User 3" }
}
},
group2: {
name: "Group 2",
users: {
uid1: { name: "User 1" },
uid4: { name: "User 4" }
}
}
};
Check:
if ("group1" in groups && "uid1" in groups["group1"].users) /* ... */;
Fetch:
var username = groups["group1"].users["uid1"].name
Remove:
delete groups["group1"].users["uid1"];
Add:
groups["group1"].users["uid4"] = { name: "User 4" };
To avoid unnecessary duplication and insert paradoxons:
// all relevant users, for look-up purposes
var allUsers = {
uid1: { name: "User 1" },
uid2: { name: "User 2" },
uid3: { name: "User 3" },
uid4: { name: "User 4" }
}
// groups reference the ID only, details are in allUsers["uid1"] etc
var groups = {
group1: {
name: "Group 1",
users: {uid1: 1, uid2: 1, uid3: 1}
},
group2: {
name: "Group 2",
users: {uid1: 1, uid4: 1 }
}
};
Check:
if ("group1" in groups && "uid1" in groups["group1"].users) /* ... */;
Fetch:
var username = allUsers["uid1"].name
Remove:
delete groups["group1"].users["uid1"];
Add:
groups["group1"].users["uid4"] = 1;
You could use a structure like the following. You would want to flesh it out with more detail, and group probably has a similar structure for an internal array of users.Also some error handling for impossible values (like id = -201) wouldn't hurt.
function Group(id, name, info)
{
var _id = id;
var _name = name;
var _info = info
this.getID = function()
{
return _id;
}
this.getName = function()
{
return _name;
}
this.getInfo = function()
{
return _info;
}
}
function GroupList()
{
var _groups = [];
this.addGroup = function(group)
{
_groups.push(group);
}
this.getGroup = function(id)
{
var group;
for(var index = 0, length = _groups.length; index < length; ++index)
{
group = _groups[index];
if (id === group.getID())
{
return group;
}
}
}
}
If you're going for a OOP style as above, I'd recommend Prototype as it makes class inheritance easier. Then it's just a matter of writing a generic List and extending from that (see http://api.prototypejs.org/language/class.html). Prototype also provides, amongst other things, a pretty broad set of functions for working with arrays and enumerables (see http://api.prototypejs.org/language/enumerable.html).
You should not care about the string matching this is wrapped by jQuery for good reasons!
The fastest way without jQuery would be
document.getElementById('idOfLiElement');
You can also use jQuery's data function to store groups for easy retrieval.
var group1 = {
name: "Group 1",
users: {
uid1: { name: "User 1" },
uid2: { name: "User 2" },
uid3: { name: "User 3" }
}
}
$('#ArbitraryElementID').data('Group 1', group1);
then you can use:
var group1 = $('#ArbitraryElementID').data('Group 1');
to retrieve the object.

Categories