Is there a way to access an array element via multiple keys? - javascript

I'm trying to store some data in an associative array in php for access in javascript later. I want to process the data in such a way that I can access it in multiple ways, say both by name and by type?
//e.g. in cpp i would do
struct SortedFruits{
std::unordered_map<std::string, Fruits> byName;
std::unordered_map<std::string, std::unordered_map<std::string, Fruits&>> byType;
}
SortedFruit fruit();
//then add them like
fruit.byName["apple"] = new Apple();
fruit.byType["red"]["apple"] = &fruit.byName["apple"];
I basically just want fruits.byType['red']['apple'] === fruits.byName['apple'] somehow. Ideally I want this to be done in php so i can store it somwhere and not recomputed, but if references/pointers can't survive inside a json I'm happy doing the sorting in javascript as well.
May I ask what's the best way to do this?

I think formatting the datas in php that way to be parsed by js later from a json is not the best way to do.
Basically you have objects Fruit that have two properties name and color. I'd just encode a json with an array of Fruit and in js map it the way I want to use those objects.
I don't think mapping the objects is the responsability of the server, it's responsability is to give the client the datas.
Edit (in response of the comment)
In JS i would even not store them in multiple maps.
const fruits = [
{color: 'red', name: 'apple'},
{color: 'red', name: 'strawberry'},
{color: 'yellow', name: 'banana'}
];
const redOnes = fruits.filter(fruit => fruit.color === 'red');
// will return [{color: 'red', name: 'apple'}, {color: 'red', name: 'strawberry'}]
const apple = fruits.find(fruit => fruit.name === 'apple');
// will return {color: 'red', name: 'apple'}

Related

Extract string from object and pass it to parent function - Typescript , React

I am trying to achieve something rather simple, but i do not know why i am so stuck on it.
I want to send data to an parent function.
This data is only acceptable in a form of a string. But my issue here is that sometimes on click event i may have multiple strings
The final goals is to send them both up
setNewFruits('banana' , 'mango')
So on click i am getting my object
...
const foundFruits = foundFruitsCategory.fruits
console.log : {name: 'banana', id: 1, color: 'yellow'}
And the if i want to extract the name only i do :
const foundAndSelectedFruit = foundFruits.map((fruit) => fruit.name)
console.log output:
['banana']
But the thing is i want to have the name only as a string banana and not as array of strings.
Yes i can say
console.log(foundAndSelectedFruit[0])
That will give me the banana , but the thing is sometimes onClick i could have two objects
console.log output:
[
{name: 'banana', id: 1, color: 'yellow'}
{name: 'mango', id: 2, color: 'orange'}
]
So the log of foundAndSelectedFruit will be
['banana','mango']
How i can extract them as seperate strings and send them to my update function ?
( The function awaits a string of name )
P.S. I already tried with forEach loop , but instead of printing my string it gives me back undefined
Have you tried the spread operator?
setNewFruits(...foundAndSelectedFruit)

How can I store data in a JavaScript Array so it can be stored in local storage?

I'm trying to build a basic web store and I'm looking for a way to store data that I already have in an Excel sheet in a JavaScript array so that I can store it in the local storage if the buyer clicks on "Add to cart", for example:
I have this data right here:
['Hoodie','Purple','cotton authentic',' Only £39.99','images/items/hoodies/hoodie (1).jpg']
['Hoodie','Light Blue','cotton authentic',' Only £39.99','images/items/hoodies/hoodie (2).jpg']
['Hoodie','Green','cotton authentic',' Only £39.99','images/items/hoodies/hoodie (3).jpg']
as you can see, it's the type of clothing, color, description, price and source of image
how can I store this in a JavaScript array so that I can create a function that upon clicking a button, adds the specific item in local storage?
First off... from a data structure point of view, your solution is: interesting
['Hoodie','Purple','cotton authentic',' Only £39.99','images/items/hoodies/hoodie (1).jpg']
['Hoodie','Light Blue','cotton authentic',' Only £39.99','images/items/hoodies/hoodie (2).jpg']
['Hoodie','Green','cotton authentic',' Only £39.99','images/items/hoodies/hoodie (3).jpg']
Generally, in an array, you want to have multiple things that are all the same kind of thing. Yes, here each hoodie is represented as an array... and all the elements of each array are strings... but each string represents some entirely different type of thing.
Really, you should be using objects to store the hoodies:
{
type: 'Hoodie',
color: 'Purple',
material: 'cotton authentic',
price: '£39.99',
image: 'images/items/hoodies/hoodie (1).jpg'
}
Now you have a single thing that has specific attributes each with a value
To show all of your hoodies, you have your array.. but now you load that array with those objects instead of having separate arrays
var hoodieArray = [{
type: 'Hoodie',
color: 'Purple',
material: 'cotton authentic',
price: '£39.99',
image: 'images/items/hoodies/hoodie (1).jpg'
},
{
type: 'Hoodie',
color: 'Light Blue',
material: 'cotton authentic',
price: '£39.99',
image: 'images/items/hoodies/hoodie (2).jpg'
},
{
type: 'Hoodie',
color: 'Green',
material: 'cotton authentic',
price: '£39.99',
image: 'images/items/hoodies/hoodie (3).jpg'
}]
Now, you have a way to store, within a single key in the localStorage, the array of separate objects each with its list of attributes simply by passing in JSON.stringify(hoodieArray)
If you have the array in numbers and want to clean them up to array of object.
For instance, let say you have arrays like the following :
let allArray = [
['Hoodie', 'Purple', 'cotton authentic', ' Only £39.99', 'images/items/hoodies/hoodie (1).jpg'],
['Hoodie', 'Light Blue', 'cotton authentic', ' Only £39.99', 'images/items/hoodies/hoodie (2).jpg'],
['Hoodie', 'Green', 'cotton authentic', ' Only £39.99', 'images/items/hoodies/hoodie (3).jpg']
]
provided you are sure of the position of each element in the sub array, you, the code below will transform all to array of object.
allArray.forEach((element, index) => {
let obj = {}
obj.type = element[0]
obj.color = element[1]
obj.material = element[2]
obj.price = element[3]
obj.image = element[4]
allArray[index] = obj
})
you can have a look at what you get in the console
console.log(allArray)
so, you can then add the reformed array to localstorage like this :
localStorage.setItem("mycart", JSON.stringify(allArray))
However, in an ideal scenario, items are added to the cart one at a time. To add an item at a time you can write a function to add item to cart and another one to get cart items as given below
addToCart(item) {
let items = getCartItem()
items = items == null ? [] : items
let found = items.find(x => x.somethingUnique == item.somethingUnique)
if (found == null || undefined) {
items.push(item)
localStorage.setItem("mycart", JSON.stringify(items))
return true;
}
return false;
}
Note
let found = items.find(x => x.somethingUnique == item.somethingUnique)
Replace somethingUnique with anything that is unique to each object, like ID etc. This is to check if an element already exist in the cart, and therefore avoids duplicates with the code
getCartItem() {
let item = localStorage.getItem("mycart")
item = item == null || undefined ? null : JSON.parse(item)
return item;
}
I hope this helps.

How to convert a plain JS object to an Immutable collection?

I have parts of a state managed with the help of Immutable collections.
For example,
const FolderModel = Record({
id: null,
name: '',
items: List()
})
const DocsModel = Record({
folder1: new FolderModel({
id: 1,
name: 'Избранное'
}),
folder2: new FolderModel({
id: 2,
name: 'Отложенное'
}),
folder3: new FolderModel({
id: 3,
name: 'Топ тендеры'
})
})
const initialState = new DocsModel()
I also save my state in a localStorage, so the problem is when retrieve the state from localStorage I don't know how to convert JS object back to a nested collection (e.g Record containing a field that is a List).
I already tried using Immutable.fromJS() method but apparently it doesn't work for Records. Did anybody face the same problem? Please help resolving it
I've had success using the transit-immutable-js lib.
From the docs:
"Transit is a serialisation format which builds on top of JSON to provide a richer set of types. It is extensible, which makes it a good choice for easily providing serialisation and deserialisation capabilities for Immutable's types."
Example usage with Records:
var FooRecord = Immutable.Record({ a: 1, b: 2, }, 'Foo'),
foo = new FooRecord(),
serialize = transit.withRecords([FooRecord]),
json = serialize.toJSON(foo);
console.log(json); //=> json string of your data
I believe you need to serialize your collection with JSON.stringify() before setting it to localStorage. After getting it back from localStorage you can deserialize it with JSON.parse()

Dexie : How to add to array in nested object

I am using Dexie IndexedDB wrapper and I am trying to add an object to an existing array which in inside a nested object. The structure looks similar to below
{
Name : 'John',
age : 33,
tags : {
skill: [{
first: '.NET',
second: 'JAVA',
third: [{special1:'sleep'},{special2:'eat'}]
}]
}
}
I have tried many way to push object special3:'run' to skill.third but without success. My last attempt looked something like this
const pathObject = {};
const fullPath = 'result.tags.skill[3].third';
pathObject[fullPath] = {special3:'run'};
db.inspections.update(id, pathObject);
The object is added outside and not inside the array 'third' something like below
{
Name : 'John',
age : 33,
tags : {
skill: [{
first: '.NET',
second: 'JAVA',
third: [{special1:'sleep'},{special2:'eat'}]
}]
skill[3]: {
third: {special3:'run'}
}
}
}
I wish to know if there a way to add to arrays in nested object using Dexie if not is there a way to achieve this using indexeddb. Help is appreciated as problem is been holding back progress
The easiest is to use Collection.modify() with a callback function to mutate your model:
db.inspections.where('id').equals(id).modify(x =>
x.tags.skill[0].third.push({special3:'run'}) );
If you want to use a keypath containing array items, it is also possible, as arrays can be looked at as objects with numeric keys:
db.inspections.update(id, {"tags.skill.0.third.3": {special3:'run'}});

Merge objects that share a common key or value

I'm loading in a big CSV to work with in javascript -- to create SVG elements from.
There is a property in the variable called code. In the CSV, there is a column called SPECIES. "Code" and "SPECIES" contain the same letter codes.
I'd like to be able to compare the data in the CSV to the var trees, and if for a particular record in the CSV, the "SPECIES" field is the same as the "code" value in the variable, I want to return the "common" value from the variable.
The CSV file has 150,000 records, which is why I don't want to add another column with common name to it.
Here is part of the variable (there are 54 objects in all):
var trees = [
{ code: 'ACPL',
common: 'Norway Maple',
genus: 'Acer',
species: 'platanoides',
family: 'Sapindaceae',
color: '#00567e'
},
{ code: 'ACRU',
common: 'Red Maple',
genus: 'Acer',
species: 'rubrum',
family: 'Sapindaceae',
color: '#0084ff'
},
{ code: 'ACSA1',
common: 'Silver Maple',
genus: 'Acer',
species: 'saccharinum',
family: 'Sapindaceae',
color: '#c3c3c3'
}
];
Here is part of the data.csv (150,000 records total here):
DIAMETER,SPECIES,longitude,latitude
15,ACPL,-73.935944,40.668076
22,ACPL,-73.934644,40.667189
28,ACSA1,-73.941676,40.667593
27,ACPL,-73.935095,40.666322
9,ACRU,-73.941297,40.667574
27,ACPL,-73.935149,40.666324
19,ACRU,-73.933664,40.666244
Here is what I've tried, which isn't working:
var treeCode = trees.forEach(function(each) { return each.code; }); // returns the value of "code" for each object in the trees variable
var treeCommon = trees.forEach(function(each) { return each.common; }); // returns the value of "color" for each object in the trees variable
var tip = d3.tip() // d3.tip is a tooltip library for D3.js
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d){if (d.SPECIES == treeCode){ // the data from the csv was loaded in earlier, and d.SPECIES returns the "SPECIES" field
return treeCommon}
})
Any thoughts about what needs to be done would be greatly appreciated! Let me know if I can clarify anything.
The full code is here: https://github.com/jhubley/street-trees/blob/master/index.html
You can see in that code that there's a looong if/else statement with hexadecimal colors. That's another example of where I want to use this approach.
Thank you for looking!
There's some great documentation for underscore at http://underscorejs.org/. D3 is a fairly robust lib so I bet some of these functions are already built in to D3 as well.
So to clarify, you want to run through the records in the CSV and pull the corresponding data from the trees object. Here's how I would do this with underscore:
// Information about each tree type
var treeInfo = [
{
code: 'ACPL',
common: 'Norway Maple',
genus: 'Acer',
species: 'platanoides',
family: 'Sapindaceae',
color: '#00567e'
},
...
];
// imported from CSV
var treeList = [
{
DIAMETER: 15,
SPECIES: "ACPL",
longitude: -73.935944,
latitude: 40.668076
}
...
]
// loop through the imported list of trees
_.each(treeList, function(){
// _.each() makes `this`` refer to the object in the list as it loops through
// find the info for this tree species
var info = _.findWhere(treeData, {"code": this.SPECIES});
// insert the keys and values from the info object into the original object from the treeList
_.extend(this, info);
})
//now treeList contains all the corresponding info (by species) from treeInfo for each tree

Categories

Resources