I'm trying to check localStorage for a nickname and if it includes the nickname remove it from the localStorage.
window.removeNickname = (n) => {
const names = localStorage['nicknames'].split(','); // Output = ["NAME 1", "NAME 2", "NAME 3"]
if (names.includes(n)) {
// HOW CAN I REMOVE THE NAME FROM THE LOCALSTORAGE HERE AND REPLACE THE LOCALSTORAGE NICKNAMES.
}
};
removeNickname('NAME 2');
You can try to remove the item from the array with split and set the new array as your nicknames.
Splice removes the items from array starting from the index that you mentioned in the first argument and removes as many elements as you set in the second argument.
window.removeNickname = (n) => {
const names = localStorage['nicknames'].split(','); // Output = ["NAME 1", "NAME 2", "NAME 3"]
if (names.includes(n)) {
localStorage.setItem(nicknames, names.splice(names.indexOf(n), 1));
}
};
This is a great use case for localDataStorage, a utility I authored. With localDataStorage you can create and manipulate Array Keys and store the value in localStorage. Some examples:
Create and initialize an Array Key in localStorage called nicknames with 3 element values:
> lds.push( 'nicknames', 'Mac', 'Bill', 'Will' );
Query the Array Key for a certain element:
> lds.contains( 'nicknames', 'Bill' );
true
Remove an element from the Array Key (specifying a value literal):
> lds.pull( 'nicknames', 'Bill' );
Get the updated key value:
> let newKey = lds.get( 'nicknames' );
['Mac', 'Will']
So your application might go something like this:
const removeNickname = (n) => {
lds.pull( 'nicknames', n );
return lds.get( 'nicknames' );
};
const addNickname = (n) => {
lds.push( 'nicknames', n ); // appends to array
return lds.get( 'nicknames' );
};
updatedNicknamesArray = removeNickname( 'Tom' );
updatedNicknamesArray = addNickname( 'Tim' );
Related
I've tried a few stack examples. an i am still just rewriting what i was hoping to be adding to ... mainly we have a list of check box items each time you check it i would like existing items to turn into a list of those object so we can use them on a 'comparing' page
const handleChange = () => {
localStorage.setItem("item", JSON.stringify(products)); <-- works as expected
var existingItems: any[] = [];
existingItems?.push({ products });
localStorage.setItem("compareItems", JSON.stringify(existingItems));
};
existingItems is always = to products i want existing items to = [{item}, {item},] and so on
detail of what products would be:
products (object of key and values frm api) = {name: "Product 1", description: "Product 1", isActiveForEntry: true, displayRank: 0, sku: "ABC123"}
You have to get the existing items first before defaulting to an empty array:
const existingItems: any[] = JSON.parse(localStorage.getItem("compareItems")) ?? [];
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
existingItems.push({ products });
localStorage.setItem("compareItems", JSON.stringify(existingItems));
See nullish coalescing operator for what the ?? means.
At each method invocation, you are initializing existingItems object then storing its value with one item being the products hence the stored object will only hold one item at a time.
You should retrieve the compareItems stored value being your existingItems then append the new products objet to it:
const handleChange = () => {
localStorage.setItem("item", JSON.stringify(products));
const compareItems = JSON.parse(localStorage.getItem("compareItems"));
var existingItems: any[] = compareItems ? compareItems : [];
existingItems.push({ products });
localStorage.setItem("compareItems", JSON.stringify(existingItems));
};
I have reference array which has values ["a","b","c","d"] .and i have another array which is obtaining as part of API which is not very consistent format .i am pointing some examples below
case 1.`{
names : ["a"],
value : [ [0],[0],[2],[4],... ]
}`
case 2. `{
names : ["a","c"],
value : [ [0,2],[0,0],[2,3],[4,4],... ]
}`
the result could be in any combination
but my requirement is to assign the value of incoming result into another array
having index same as my reference array
for example : in
case 1
`
let finalArray = [["0",null,null,null],
["0",null,null,null],
["2",null,null,null].... ]
`
for case 2:
`let finalArray = [["0",null,"2",null],
["0",null,"0",null],
["2",null,"3",null].... ]
`
alse attaching a fiddle with my inputs below
jsfiddle link to problem
any suggestions?
i am trying to use minimal for loops for performance optimization
Hope this will be helpful.
var refArray = ["a","b","c","d"];
setTimeout(()=>{processResult({
"names" : ["a"],
"value" : [ [0],[0],[2],[4]]
})},2000);
setTimeout(()=>{processResult(
{
"names" : ["a","c"],
"value" : [ [0,2],[0,0],[2,3],[4,4]]
})},4000);
setTimeout(()=>{processResult(
{
"names" : ["d","c"],
"value" : [ [0,2],[0,0],[2,3],[4,4]]
})},6000);
function processResult (result) {
let res = result.value;
let resArray = res.map((el)=>{
let k=Array(refArray.length).fill(null);
refArray.forEach((e,i)=>{
let indx = result.names.indexOf(e);
if(indx>=0){
k[i] = el[indx]
}
});
return k;
})
console.log("result",resArray)
}
Below is what I could think of that would require least iterations.
var refArray = ["a", "b", "c", "d"];
setTimeout(()=>{processResult({
"names" : ["a"],
"value" : [ [0],[0],[2],[4]]
})},2000);
setTimeout(()=>{processResult(
{
"names" : ["a","c"],
"value" : [ [0,2],[0,0],[2,3],[4,4]]
})},4000);
setTimeout(()=>{processResult(
{
"names" : ["d","c"],
"value" : [ [0,2],[0,0],[2,3],[4,4]]
})},6000);
function processResult(result) {
//This map will contain max names matched in the result
var maxItemsFromResult = {};
//Find the indexes in refArray and fill map
//e.g. 1st- {0:0}, 2nd - {0:0, 1:2}, 3rd - {0:3, 1:2}
result.names.forEach((item, index) => {
let indexFound = refArray.indexOf(item);
if (indexFound > -1) {
maxItemsFromResult[index] = indexFound;
}
});
//for performance if no key matched exit
if (Object.keys(maxItemsFromResult).length < 1) {
return;
}
//This will be final result
let finalArray = [];
//Because finalArray's length shuld be total items in value array loop through it
result.value.forEach((item, itemIndex) => {
//Create a row
let valueArray = new Array(refArray.length).fill(null);
//Below will only loop matched keys and fill respective position/column in row
//i'm taking all the matched keys from current value[] before moving to next
Object.keys(maxItemsFromResult).forEach((key, index) => {
valueArray[maxItemsFromResult[key]] = item[index];//get item from matched key
});
finalArray.push(valueArray);
});
console.log(finalArray);
return finalArray;
}
I have a JSON file like below:
[
{"fields":{category_class":"CAT2",category_name":"A"},"pk":1 },
{"fields":{category_class":"CAT1",category_name":"B"},"pk":2 },
{"fields":{category_class":"CAT1",category_name":"C"},"pk":3 },
{"fields":{category_class":"CAT2",category_name":"D"},"pk":4 },
{"fields":{category_class":"CAT3",category_name":"E"},"pk":5 },
{"fields":{category_class":"CAT1",category_name":"E"},"pk":6 },
]
I want to create an array of objects from the above JSON which will have two properties. i) CategoryClass ii) CategoryNameList. For example:
this.CategoryClass = "CAT1"
this.CategoryNameList = ['B','C','E']
Basically i want to select all categories name whose category class is CAT1 and so forth for other categories class. I tried this:
var category = function(categoryClass, categoryNameList){
this.categoryClass = categoryClass;
this.categoryList = categoryNameList;
}
var categories = [];
categories.push(new category('CAT1',['B','C','E'])
Need help.
You can use a simple filter on the array. You have a few double quotes that will cause an error in you code. But to filter only with CAT1 you can use the filter method
var cat1 = arr.filter( value => value.fields.category_class === "CAT1");
I would suggest this ES6 function, which creates an object keyed by category classes, providing the object with category names for each:
function groupByClass(data) {
return data.reduce( (acc, { fields } ) => {
(acc[fields.category_class] = acc[fields.category_class] || {
categoryClass: fields.category_class,
categoryNameList: []
}).categoryNameList.push(fields.category_name);
return acc;
}, {} );
}
// Sample data
var data = [
{"fields":{"category_class":"CAT2","category_name":"A"},"pk":1 },
{"fields":{"category_class":"CAT1","category_name":"B"},"pk":2 },
{"fields":{"category_class":"CAT1","category_name":"C"},"pk":3 },
{"fields":{"category_class":"CAT2","category_name":"D"},"pk":4 },
{"fields":{"category_class":"CAT3","category_name":"E"},"pk":5 },
{"fields":{"category_class":"CAT1","category_name":"E"},"pk":6 },
];
// Convert
var result = groupByClass(data);
// Outut
console.log(result);
// Example look-up:
console.log(result['CAT1']);
Question : Basically i want to select all categories name whose category class is CAT1 and so forth for other categories class
Solution :
function Select_CatName(catclass,array){
var CatNameList=[]
$(array).each(function(){
if(this.fields.category_class==catclass)
CatNameList.push(this.fields.category_name)
})
return CatNameList;
}
This function return the Desired Category Name List, you need to pass desired catclass and array of the data , as in this case it's your JSON.
Input :
Above function calling :
Output :
Hope It helps.
I have an object, with nested objects. How do I target a specific index of the object and loop through all the nested values of image. As you will note the length of the nested objects vary.
Target example: productArray[0].image = test1.png, test2.png, test3.png
var products = [
//item1
{
identifier: "item-0",
image: {
"img1": "test1.png",
"img2": "test2.png",
"img3": "test3.png"
}
},
//item2
{
identifier: "item-1",
image: {
"img1": "test1.png",
"img2": "test2.png"
}
},
//item3
{
identifier: "item-2",
image: {
"img1": "test1.png",
"img2": "test2.png",
"img3": "test3.png",
"img4": "test4.png",
"img5": "test5.png",
"img6": "test6.png",
"img7": "test7.png"
}
}
];
We can do this. What you need to do is a simple loop through the object at a specific index, or you can target them all. Note that the image object is not an array, so it will not have an accurate length property.
Target all indexes:
for(var i = 0; i < products.length; i++) {
console.log("Item: " + i);
var images = products[i].image;
for(var a in images)
console.log(images[a]);
}
Target specific:
for(var i in products[0].image)
console.log(products[0].image[i]);
I used a for loop here, but you can use a while loop if you would like.
example
Steps:
You need to iterate over your original array of products. products
Each element (product) will be in format { identifier: "", image : {"img1" : "img2", ..}} products[i]
You get the image property of current product - this is an object. products[i].image
Now you need to iterate over the properties of the image object. products[i].image[j]
Code:
for(var i = 0; i < products.length; i++)
{
for(var j in products[i].image)
{
// Here you have all the images for the current product.
// You can print them, group them or whatever you want to do with them
console.log(products[i].image[j]);
}
}
Also you can change the code (introduce variables) to be more readable.
var strs = (function( obj ) {
var ret = [];
for( im in obj ) {
ret.push( obj[im] );
//You could access each image URL here
//ad strs in the end will have all of them
//comma-separated after this code completes
// im is the key, obj[ im ] the value
}
return ret.join(',');
})( products[0].image );
console.log( strs );
WORKING JS FIDDLE DEMO
Here is another way of doing this, with newer functions in ECMAScript 5
var images = Object.keys(products[2].image).map(function(key){
return products[2].image[key]
})
console.log(images) // Returns: ["test1.png", "test2.png", "test3.png", "test4.png", "test5.png", "test6.png", "test7.png"]
How It Works:
Object#keys returns an array of key names. Array#map creates a new array using the keys from Object#keys. By looking up the key from the object you get the value, which will be the image name.
JS FIDDLE
I want to navigate up and down an JavaScript Object given an item of an object. An example object:
var items = {
"5" : ["name", "link2"],
"8" : ["name 2", "link 2"],
"11" : ["name 3", "link 3"]
}
Now, given I have the item items["8"]. I want to get previous and next item respectively.
getItemBefore = function(index) {
// index holds 8
// should return "5"
}
getItemAfter = function(index) {
// index hold 8
// should return 11
}
How can I get those items?
The keys that an object holds can be retrieved as an array with Object.keys(<var>). The order of the keys in the array is arbitrary; you need to sort them before indexing. An option is the built-in sort() method for arrays, which is especially useful because custom comparison functions can be provided (see below). Default order is alphabetical.
Once you get the ordered array, you only need to look up where your item is in the array and return the next and previous elements from it:
var keys = Object.keys(items).sort();
var loc = keys.indexOf(item);
Given that loc > -1 (that is, the item exists):
Previous item: items[keys[loc-1]], but check that loc > 0 (it's not the first one).
Next item: items[keys[loc+1]], but check that loc < keys.length (it's not the last one).
Object.keys is compatible with Javascript 1.85+; here is a workaround for older browsers.
Alternative orderings
Numerical
If you want the keys to have a numerical order, use this comparison function:
var keys = Object.keys(items).sort( function(a,b) {
return b - a;
});
Creation (or Modification) Time
If you want to work with creation order instead of alphanumeric, the items must hold their creation time. Something like:
<value>.index = Date.getTime();
items['<item>'] = <value>;
Then, the sort() method needs the following comparison function:
var keys = Object.keys(items).sort( function(a,b) {
return b.index - a.index;
});
This can be easily extended to last modification ordering or similar.
Creation Order
Notice that the former solution only works if the items are created more than 1 ms apart, which would be suitable for user actions. If the items are added faster, use this instead of the timestamp:
<value>.index = Object.keys(items).length;
Or, alternatively, keep an external counter with the number of items in the object.
This answer builds upon #lemonzi's answer, see his answer for more detailed explanations.
I just wanted to add a working example for everyone struggling with this:
var items = {
"5": ["name", "link2"],
"8": ["name 2", "link 2"],
"11": ["name 3", "link 3"]
};
var getItem = function(key, i) {
var keys = Object.keys(items).sort(function(a,b){return a-b;});
var index = keys.indexOf(key);
if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) {index = index+i;}
return items[keys[index]];
}
console.log(getItem("8",-1));
console.log(getItem("8",+1));
jsfiddle: https://jsfiddle.net/p09yL01f/3/
This way you only need one function to change item.
The .sort(function(a,b){return a-b;}) sorts the array numerical.
The if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) { checks that the item is not the first or the last index in the array, and if it is, it returns the index itself.
If you want to display a message if the item is the first or the last, use this instead:
if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) {return items[keys[index+i]];}
else {return (i==1?"last":"first")+" item";}
var items = {
"5": ["name", "link2"],
"8": ["name 2", "link 2"],
"11": ["name 3", "link 3"]
};
var getItem = function(key, i) {
var keys = Object.keys(items).sort(function(a,b){return a-b;});
var index = keys.indexOf(key);
if ((i==-1 && index>0) || (i==1 && index<keys.length-1)) {return items[keys[index+i]];}
else {return (i==1?"last":"first")+" item";}
}
console.log(getItem("5",-1));
console.log(getItem("11",+1));
jsfiddle: https://jsfiddle.net/p09yL01f/4/
The (i==1?"last":"first") is called a ternary operator, read about it.
This is a bit tricky, because technically according to the ECMAScript specifications, the order of properties in an object is implementation specific. That means there's no guarantee in the language that your properties will be in the same order each time you access them. If you're relying on that, there's a potential there could be a problem.
See this bug in Chrome. It states that Chrome doesn't promise to return your keys in any particular order, and it's been marked "WONTFIX" for 4-5 years now. That means that you can't rely on that behavior in Chrome, and here's another post indicating that now IE9 has the same "issue".
So, I would recommend that you create your own object to manage your keys, and use a JavaScript object behind the scenes to store your keys.
Here's something I threw together, it doesn't support deletes and it has no bounds checking, but it should serve your purposes. Fiddle here.
function orderedObject()
{
this.keys = [];
this.keyIndex = {};
this.store = {};
}
orderedObject.prototype.addItem = function(key,value)
{
this.keyIndex[key] = this.keys.length;
this.keys.push(key);
this.store[key] = value;
}
orderedObject.prototype.getItem = function(key)
{
return this.store[key];
}
orderedObject.prototype.getKeyBefore = function(key)
{
return this.keys[this.keyIndex[key] - 1];
}
orderedObject.prototype.getKeyAfter = function(key)
{
return this.keys[this.keyIndex[key] + 1];
}
var testObject = new orderedObject();
testObject.addItem("5" , ["name", "link2"]);
testObject.addItem("8" , ["name 2", "link 2"]);
testObject.addItem("11" , ["name 3", "link 3"]);
console.log(testObject.getKeyBefore("8"))
console.log(testObject.getKeyAfter("8"))
Would an array of objects be more appropriate here? The example below could be wrapped in an object and making the nextItem() and prevItem() methods. With this you might also need some bounds checking.
var items = [];
items[0] = {index : '5', name : 'name', link : 'link2'};
items[1] = {index : '8', name : 'name 2', link : 'link 2'};
items[2] = {index : '11', name : 'name 3', link : 'link 3'};
//then access them like this
var nextItem = function (index) {
var i = 0,
max = items.length;
for (i; i < max; i += 1) {
if (items[i].index === index) {
return items[i + 1];
}
}
return 'not found';
};
var prevItem = function (index) {
var i = 0,
max = items.length;
for(i; i < max; i += 1) {
if (items[i].index === index) {
return items[i - 1];
}
}
return 'not found';
};
//the nextItem object after 5 is shown in the console.
console.dir(nextItem('5'));