I'm trying to loop through localStorage to get ALL items through localStorage.length that works with my search algorithm. If i change: i < localStorage.length inside the for loop to simply a number, i.e: for (i=0; i<100; i++) instead of: (i=0; i<=localStorage.length-1; i++), everthing works. However, I do realize the problem might lie in the search algorithm.
The code getting all items:
var name = new Array();
for (var i = 0; i <= localStorage.length - 1; i++) { // i < 100 works perfectly
key = localStorage.key(i);
val = localStorage.getItem(key);
value = val.split(","); //splitting string inside array to get name
name[i] = value[1]; // getting name from split string
}
My working (!?) search algorithm:
if (str.length == 0) {
document.getElementById("searchResult").innerHTML = "";
}
else {
if(str.length > 0) {
var hint = "";
for(var i=0; i < name.length; i++) {
if(str.toLowerCase() == (name[i].substr(0, str.length)).toLowerCase()) { //not sure about this line
if(hint == "") {
hint = name[i];
} else {
hint = hint + " <br /> " + name[i];
}
}
}
}
}
if(hint == "") {
document.getElementById("searchResult").innerHTML=str + " står inte på listan";
} else {
document.getElementById("searchResult").innerHTML = hint;
}
}
What is wrong with my localStorage.length, or what is wrong with the search algorithm?
localStorage is an object, not an array.
Try for(var i in window.localStorage):
for(var i in window.localStorage){
val = localStorage.getItem(i);
value = val.split(","); //splitting string inside array to get name
name[i] = value[1]; // getting name from split string
}
Problem now SOLVED. The issue was that each time data was saved to localStorage, one extra empty item was stored at the bottom of the local db as a consequence of an incorrectly written for loop (in the setItem part.) arrayIndex < guestData.length should have been arrayIndex < guestData.length-1. arrayIndex < guestData.length-1 stores all items without creating an empty item at the bottom of the database which later messed up the search algorithm, as the last value to be search was undefined (the empty item).
print all localStorage items
and exclude the internal properties and methods.
for(var key in localStorage){
if(localStorage.hasOwnProperty(key)) {
console.log(key + ' : ' + localStorage.getItem(key));
}
}
Related
I have an array called countriesData that stores names for various countries, like this:
[Germany,France,Canada,Austria,Switzerland,Spain]
I'm trying to iterate over each element in that array, the idea is use each country in a query search over an external API, and then save the length of items in that external API. To put it simple, Im going through each country and counting how many items from that country are stored in an external database.
I have no problem accessing the database outside of the loop, however, I am unable to access it while inside the for iterator.This is my code:
for (var iter = 0; iter < countriesData.length; iter++) {
var obj = [];
var country = countriesData[iter]
var items;
var itemsCountry = 0;
$http.get("https://api.discogs.com/database/search?q={?country==" + country + " }&token=zwxZExVZTenjPTKumVeTDVRuniqhQLAxymdzSxUQ").then(function(response) {
items = response.data.pagination.items;
})
var str = "";
obj.push(countriesData[iter]);
obj.push(items);
for (var J = 0; J < myStats.data.length; J++) {
if (myStats.data[J].country == countriesData[iter]) {
itemsCountry++;
str += myStats.data[J].title + ", ";
}
}
obj.push(itemsCountry);
var str2 = str.substring(0, str.length - 2);
obj.push(str2);
newData.push(obj);
console.log("new obj : " + obj)
}
Basically, I need the var items to be updated acording to the length of the response data from http.get
This is an example of what I get once I console.log the obj:
France,,2,Thriller, D'eux
As you can see, the second element in the array is empty when it should have been an integer representing how many France related items where found in the database...
What is it that Im doing wrong? I get that the database is big and there might not be enough time for it to load. Any idead?
Thanks in advance :)
The problem is that your data call is asynchronous and hasn't completed before you try to push the data to the array.
function getCountryData(country) {
var obj = [];
var items;
var itemsCountry = 0;
$http.get("https://api.discogs.com/database/search?q={?country==" + country + " }&token=zwxZExVZTenjPTKumVeTDVRuniqhQLAxymdzSxUQ").then(function(response) {
items = response.data.pagination.items;
var str = "";
obj.push(country);
obj.push(items);
for (var J = 0; J < myStats.data.length; J++) {
if (myStats.data[J].country == countriesData[iter]) {
itemsCountry++;
str += myStats.data[J].title + ", ";
}
}
obj.push(itemsCountry);
var str2 = str.substring(0, str.length - 2);
obj.push(str2);
newData.push(obj);
console.log("new obj : " + obj)
})
}
for (var iter = 0; iter < countriesData.length; iter++) {
var country = countriesData[iter];
getCountryData(country);
}
I am trying to use a for loop to loop through an array and check the first letter of each word in the array and check to see if it starts with an M, but I can't seem to figure out how to correctly set that up.
So far I have this:
for (var animalsName = cats[0]; animalsName <= cats; animalsName++){
if (animalsName.charAt(0) == 'M') {
console.log("No treat for " + animalsName + ".");
} else {
console.log(animalsName + " loved their treat!");
}
}
You are very close.
I have made minor change in the for loop to iterate correctly and fetch the first character of the animal name.
var cats = [];
cats.push('mname1');
cats.push('tname1');
cats.push('mname2');
cats.push('Mname3');
for (var index = 0; index < cats.length; index++){
var animalsName = cats[index];
if (animalsName.substr(0,1).toLowerCase() === 'm') {
console.log("No treat for " + animalsName + ".");
} else {
console.log(animalsName + " loved their treat!");
}
}
for (let i = 0; i < cats.length; i += 1) {
if (cats[i].charAt(0).toLowerCase() === 'm') {
// do whatever you want
}
}
This will loop over the cats array and check the first letter--charAt(0)--of each element in the array. If the first letter, converted to lower case, is 'm', then you do whatever you want.
Following were an output from an array returned by following function:
$scope.variantOptions = $scope.variantLists.join(", ");
medium,small,medium,small,small
How can I sort the result, so it represent the output as:
medium x 2,small x 3
EDIT
addCount function:
$scope.addCount = function($index){
$scope.counter = 1;
if($scope.activity['variant'][$index]['count'] != undefined ){
$scope.counter = parseInt($scope.activity['variant'][$index]["count"]) +1;
$scope.variantLists.push($scope.activity['variant'][$index]['variant_dtl_name']);
}
$scope.activity['variant'][$index]["count"] = $scope.counter;
console.log(arraySimplify($scope.variantLists));
};
Thanks!
pass your '$scope.variantLists' arry into this function it will give you the expected result.
function arraySimplify(arr){
arr.sort();
var rslt = [], element =arr[0] ,count = 0 ;
if(arr.length === 0) return; //exit for empty array
for(var i = 0; i < arr.length; i++){
//count the occurences
if(element !== arr[i]){
rslt.push(element + ' x ' + count);
count =1;
element = arr[i];
}
else{
count++;
}
}
rslt.push(element + ' x ' + count);
return rslt.join(', ');
}
Your code is working:
for (var i = 0;i < $scope.variantLists.length;i++) {
obj[arr[i]] = (obj[arr[i]] || 0) + 1;
}
Gives you an object:
obj = {medium: 2, small: 3}
To see it without having to go into the console, you can just alert the object after the 'for' loop:
alert(obj);
To get the EXACT string you want:
var string = "";
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var count = validation_messages[key];
string += key + " x " + count;
}
}
Although it may look like an entry in Code Golf but this is one of the rare times when Array.reduce makes sense.
var r = a.sort().reduce(
function(A,i){
A.set(i, (!A.get(i))?1:A.get(i)+1);
return A;
},new Map());
Which makes basically what Jon Stevens proposed but in a more modern and highly illegible way. I used a Map because the order in a normal Object dictionary is not guaranteed in a forEach loop. Here r.forEach(function(v,k,m){console.log(k + ":" + v);}) gets printed in the order of insertion.
I'm trying to removal duplicates from a sorted list.
I wrote this script.
for(var i = 0; i < duplicateAuthors.length - 1; i++){
if(duplicateAuthors[i] == duplicateAuthors[i + 1]) { continue; }
else{
uniqAuthors.push(duplicateAuthors[i]);
}
}
It works except it does not capture unique values in the list. What am I doing wrong?
var uniqAuthors = [];
for(var i = 0; i < duplicateAuthors.length; i++){
if(uniqAuthors.indexOf(duplicateAuthors[i]) == -1) {
uniqAuthors.push(duplicateAuthors[i]);
}
}
The above code checks whether an object exist in an array or not, if not add it to array. Hence, at the end we will have an array of unique values.
Since object keys have to be unique I realized that you could also do the following to isolate unique values.
var uniqs = {};
for(var i = 0; i < duplicateAuthors.length ; i++){
uniqs[duplicateAuthors[i]] = null;
}
var uniqAuthors = Object.keys(uniqs);
This will take advantage of the fact that it's already sorted.
var previous;
var current;
for(var i = 0; i < duplicateAuthors.length; i++){
current = duplicateAuthors[i];
if (current && current != previous) {
uniqAuthors.push(current);
previous = current;
}
}
I have a string with repeated letters. I want letters that are repeated more than once to show only once.
Example input: aaabbbccc
Expected output: abc
I've tried to create the code myself, but so far my function has the following problems:
if the letter doesn't repeat, it's not shown (it should be)
if it's repeated once, it's show only once (i.e. aa shows a - correct)
if it's repeated twice, shows all (i.e. aaa shows aaa - should be a)
if it's repeated 3 times, it shows 6 (if aaaa it shows aaaaaa - should be a)
function unique_char(string) {
var unique = '';
var count = 0;
for (var i = 0; i < string.length; i++) {
for (var j = i+1; j < string.length; j++) {
if (string[i] == string[j]) {
count++;
unique += string[i];
}
}
}
return unique;
}
document.write(unique_char('aaabbbccc'));
The function must be with loop inside a loop; that's why the second for is inside the first.
Fill a Set with the characters and concatenate its unique entries:
function unique(str) {
return String.prototype.concat.call(...new Set(str));
}
console.log(unique('abc')); // "abc"
console.log(unique('abcabc')); // "abc"
Convert it to an array first, then use Josh Mc’s answer at How to get unique values in an array, and rejoin, like so:
var nonUnique = "ababdefegg";
var unique = Array.from(nonUnique).filter(function(item, i, ar){ return ar.indexOf(item) === i; }).join('');
All in one line. :-)
Too late may be but still my version of answer to this post:
function extractUniqCharacters(str){
var temp = {};
for(var oindex=0;oindex<str.length;oindex++){
temp[str.charAt(oindex)] = 0; //Assign any value
}
return Object.keys(temp).join("");
}
You can use a regular expression with a custom replacement function:
function unique_char(string) {
return string.replace(/(.)\1*/g, function(sequence, char) {
if (sequence.length == 1) // if the letter doesn't repeat
return ""; // its not shown
if (sequence.length == 2) // if its repeated once
return char; // its show only once (if aa shows a)
if (sequence.length == 3) // if its repeated twice
return sequence; // shows all(if aaa shows aaa)
if (sequence.length == 4) // if its repeated 3 times
return Array(7).join(char); // it shows 6( if aaaa shows aaaaaa)
// else ???
return sequence;
});
}
Using lodash:
_.uniq('aaabbbccc').join(''); // gives 'abc'
Per the actual question: "if the letter doesn't repeat its not shown"
function unique_char(str)
{
var obj = new Object();
for (var i = 0; i < str.length; i++)
{
var chr = str[i];
if (chr in obj)
{
obj[chr] += 1;
}
else
{
obj[chr] = 1;
}
}
var multiples = [];
for (key in obj)
{
// Remove this test if you just want unique chars
// But still keep the multiples.push(key)
if (obj[key] > 1)
{
multiples.push(key);
}
}
return multiples.join("");
}
var str = "aaabbbccc";
document.write(unique_char(str));
Your problem is that you are adding to unique every time you find the character in string. Really you should probably do something like this (since you specified the answer must be a nested for loop):
function unique_char(string){
var str_length=string.length;
var unique='';
for(var i=0; i<str_length; i++){
var foundIt = false;
for(var j=0; j<unique.length; j++){
if(string[i]==unique[j]){
foundIt = true;
break;
}
}
if(!foundIt){
unique+=string[i];
}
}
return unique;
}
document.write( unique_char('aaabbbccc'))
In this we only add the character found in string to unique if it isn't already there. This is really not an efficient way to do this at all ... but based on your requirements it should work.
I can't run this since I don't have anything handy to run JavaScript in ... but the theory in this method should work.
Try this if duplicate characters have to be displayed once, i.e.,
for i/p: aaabbbccc o/p: abc
var str="aaabbbccc";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 ){
return obj;
}
}
).join("");
//output: "abc"
And try this if only unique characters(String Bombarding Algo) have to be displayed, add another "and" condition to remove the characters which came more than once and display only unique characters, i.e.,
for i/p: aabbbkaha o/p: kh
var str="aabbbkaha";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 && str.lastIndexOf(obj,i-1)==-1){ // another and condition
return obj;
}
}
).join("");
//output: "kh"
<script>
uniqueString = "";
alert("Displays the number of a specific character in user entered string and then finds the number of unique characters:");
function countChar(testString, lookFor) {
var charCounter = 0;
document.write("Looking at this string:<br>");
for (pos = 0; pos < testString.length; pos++) {
if (testString.charAt(pos) == lookFor) {
charCounter += 1;
document.write("<B>" + lookFor + "</B>");
} else
document.write(testString.charAt(pos));
}
document.write("<br><br>");
return charCounter;
}
function findNumberOfUniqueChar(testString) {
var numChar = 0,
uniqueChar = 0;
for (pos = 0; pos < testString.length; pos++) {
var newLookFor = "";
for (pos2 = 0; pos2 <= pos; pos2++) {
if (testString.charAt(pos) == testString.charAt(pos2)) {
numChar += 1;
}
}
if (numChar == 1) {
uniqueChar += 1;
uniqueString = uniqueString + " " + testString.charAt(pos)
}
numChar = 0;
}
return uniqueChar;
}
var testString = prompt("Give me a string of characters to check", "");
var lookFor = "startvalue";
while (lookFor.length > 1) {
if (lookFor != "startvalue")
alert("Please select only one character");
lookFor = prompt(testString + "\n\nWhat should character should I look for?", "");
}
document.write("I found " + countChar(testString, lookFor) + " of the<b> " + lookFor + "</B> character");
document.write("<br><br>I counted the following " + findNumberOfUniqueChar(testString) + " unique character(s):");
document.write("<br>" + uniqueString)
</script>
Here is the simplest function to do that
function remove(text)
{
var unique= "";
for(var i = 0; i < text.length; i++)
{
if(unique.indexOf(text.charAt(i)) < 0)
{
unique += text.charAt(i);
}
}
return unique;
}
The one line solution will be to use Set. const chars = [...new Set(s.split(''))];
If you want to return values in an array, you can use this function below.
const getUniqueChar = (str) => Array.from(str)
.filter((item, index, arr) => arr.slice(index + 1).indexOf(item) === -1);
console.log(getUniqueChar("aaabbbccc"));
Alternatively, you can use the Set constructor.
const getUniqueChar = (str) => new Set(str);
console.log(getUniqueChar("aaabbbccc"));
Here is the simplest function to do that pt. 2
const showUniqChars = (text) => {
let uniqChars = "";
for (const char of text) {
if (!uniqChars.includes(char))
uniqChars += char;
}
return uniqChars;
};
const countUnique = (s1, s2) => new Set(s1 + s2).size
a shorter way based on #le_m answer
let unique=myArray.filter((item,index,array)=>array.indexOf(item)===index)