So i have a string, and I'm trying to join the content; if the val length is less than 10 chars, join it with the next value. But when i try this code, it joins with the same val instead of the next one.
//Set the regex.
myregex = /(<p>.*?<\/p>)/g;
//Variable string.
content = Example: <p>Hello</p><p>This is my test content</p><p>etc</p>
$(content.match(myregex)).each(function (key, val) {
var test = $(val).text();
if (test.length < 10) {
var n = val.concat(val);
$('#mydiv').append('<div>' + n + '</div>');
} else {
$('#mydiv').append('<div>' + val + '</div>');
}
})
This line here: val.concat(val), is indeed duplicating your content. What you need to do is grab the next value from the regex instead of the current one. Something like the following should work.
var matches = content.match(myregex),
myDiv = $('#mydiv');
for (var i = 0, len = matches.length; i < len; i++){
if (i + 1 < len && matches[i].length < 10){
myDiv.append('<div>' + matches[i].concat(matches[i+1]) + '</div>');
i += 1;
}
else myDiv.append('<div>' + matches[i] + '</div>');
}
val and val are the same thing, so of course val.concat(val) will duplicate it.
If you want to use $.each, I think it might be better to join with the previous value, because you don't know what the next one will be yet.
var previous = [];
$(content.match(myregex)).each(function (key, val) {
var test = $(val).text();
if (test.length < 10) {
previous = val;
} else {
if(previous.length) {
val = previous.concat(val);
}
$('#mydiv').append('<div>' + val + '</div>');
previous = [];
}
});
Related
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)
Is there a way to include variables in each iteration of a javascript loop? For example if I put this code into a loop
if (e1) {item_text += '{id:"' + id[1] + '",lvl:' + e1lvl + '},<wbr>'}
if (e2) {item_text += '{id:"' + id[2] + '",lvl:' + e2lvl + '},<wbr>'} // etc
and do something like
for (n = 0; n < id.length; n++) {
if (e/*concat var e w/var n?*/) {
item_text += '{id:"' + id[1] + '",lvl:' + e/*concat var e w/var n?*/lvl + '},<wbr>'
}
}
Is there a way to change the number in the var names (e1 -> e2 etc) each iteration or do i just have to keep it the long way and write everything out on its own line?
It would be possible, though highly not recommended, to use eval to come up with the variable name:
const e1lvl1 = 'foo';
const e2lvl1 = 'bar';
for (let i = 1; i < 3; i++) {
console.log(eval('e' + i + 'lvl1'));
}
But it would be better to fix your script's architecture so that this isn't necessary: put each e#lvl into an array, and then access the appropriate index of the array on each iteration:
const elvl = [
'foo',
'bar'
];
let item_text = '';
for (let i = 0; i < elvl.length; i++) {
item_text += 'lvl: ' + elvl[i] + '\n';
}
console.log(item_text);
Arrays/Objects exist in javascript for a reason! Simplify your code. There is no reason to have e1, e1l, e2... as variables. Add them to an object and access them by key, or add them to an array, and loop through them. There are many javascript functions as well that will allow you to ensure all elements match a certain condition.
function submit() {
var e = {};
var idx = 28;
for (var i = 0; i <= 24; i++) {
e[i] = {};
e[i].key = document.getElementById(`ench${i}`).checked
e[i].value = $.trim(form.elements[idx].value)
idx += 2;
}
// Check condition
if (Object.values(e).some(e => e.key)) {
//One of the checked items was true
}
}
I would agree that you should change your code to use arrays.
To answer your question though, since your e1 and e1lvl variables look to be global scope, you can access them like this
window["e1"]
window["e1lvl"]
Give this a try
for (n = 0; n < id.length; n++) {
if (window["e" + n]) {
item_text += '{id:"' + id[n] + '",lvl:' + window["e" + n + "lvl"] + '},<wbr>';
}
}
I have an array that returns some numbers like 222.000,333.000,444.000,555.000. Ideally I want to format so it places a breakline "\n" after every other number. i.e. Would be like
222.000,333.000
444.000,555.000
Can it be done by modifying the lines below?
n107 = parseFloat(output1),
n108 = parseFloat(output2),
n109 = parseFloat(output3),
n110 = parseFloat(output4),
list = [];
// add values to array if they're not NaN or > 0
if (n1) {
list.push(n1);
}
if (n2) {
list.push(n2);
}
if (n3) {
list.push(n3);
}
if (n4) {
list.push(n4);
}
if (n5) {
list.push(n5);
}
if (n6) {
list.push(n6);
}
// combine values into a string separated with commas
document.getElementById('inputTextToSave').innerHTML = list.join(",");
This is not a optimal solution.but it works
n107 = parseFloat("222.00"),
n108 = parseFloat("333.00"),
n109 = parseFloat("444.000"),
n110 = parseFloat("55.00"),
list = [n107,n108,n109,n110];
// combine values into a string separated with commas
//document.getElementById('inputTextToSave').innerHTML = list.join("</br>");
var j =1;
var htmlString = '';
for(var i =0; i< list.length; i++){
if(j<2){
htmlString += list[i]+",";
j++;
}else{
htmlString += list[i]+"</br>";
j=1;
}
}
document.getElementById('inputTextToSave').innerHTML = htmlString;
<div id="inputTextToSave"></div>
You need to create your own string in a loop instead of using join().
There are lots of ways to create the loop...the key is to check the index within the loop to determine which separator to use
var list = [222.000,333.000,444.000,555.000];
var res = list.reduce((newStr, currVal, index) =>
newStr += (index % 2 ===1 ? ',' :'\n') + currVal );
document.getElementById('inputTextToSave').innerHTML = res;
<pre id="inputTextToSave"></pre>
It can be done by using Array.reduce method.
const list = ['222.000', '333.000', '444.000', '555.000']
const result = list.reduce((memo, item, index) => {
const comma = (index+1)%2 === 0 ? ',' : ''
const lineBreak = (index+1)%2 === 0 ? '<br />' : ''
memo += comma + item + lineBreak
return memo
}, '')
document.getElementById('inputTextToSave').innerHTML = result;
<div id="inputTextToSave"></div>
you can try this function
function addBrakes(array){
let cutPoint = 3 // set where you want to cut
for(i=1; i<=array.length; i++){
if(i%cutPoint == 0){
array.splice(i, 0, "<br>")
}
}
}
Another option:
document.getElementById('inputTextToSave').innerHTML =
list.join(',').replace(/([^,]+,[^,]+),/g, '$1<br>')
I have a multi-dimensional array. I need some sort of loop to randomly pick a string in the array and check to see if that string contains a character. If it doesn't, then repeat until it finds one.
I wrote a for loop that checks the array for the string, BUT it starts from 0 and works its way through the array until it finds it. I need it randomly pick a string in the array...any help?
jsFiddle --> http://jsfiddle.net/hz2MZ/1/
jQuery
$(document).ready(function() {
var myarr = [{"Name":"Bob", "Char":"134"},
{"Name":"Phil", "Char":"134"},
{"Name":"Jane", "Char":"1"},
{"Name":"Don", "Char":"4"},
{"Name":"Dan", "Char":"2"},
{"Name":"Jan", "Char":"12"},
{"Name":"Bill", "Char":"24"},
{"Name":"Sam", "Char":"14"},
{"Name":"Jake", "Char":"23"},
{"Name":"Ben", "Char":"3"}];
$('button').click(function() {
for(var i = 0; i < myarr.length; i++) {
if(myarr[i].Char.indexOf('2') !== -1) {
alert("Name: " + myarr[i].Name + "\nChar: " + myarr[i].Char);
return;
} else {}
}
});
});
My solution
$('button').click(function () {
var found = false;
while (!found) {
var randomIndex = Math.floor(Math.random() * myarr.length);
if (myarr[randomIndex].Char.indexOf('2') !== -1) {
alert("Name: " + myarr[randomIndex].Name + "\nChar: " + myarr[randomIndex].Char);
found = true;
} else {}
}
});
edit
Updated endless loop problem
$('button').click(function () {
var found = false;
var maxRandom = 20;
var currentRandom = 0;
while (!found && currentRandom < maxRandom) {
var randomIndex = Math.floor((Math.random() * myarr.length));
currentRandom++;
if (myarr[randomIndex].Char.indexOf('2') !== -1) {
alert("Name: " + myarr[randomIndex].Name + "\nChar: " + myarr[randomIndex].Char);
found = true;
} else {}
}
}
One approach is to copy the array, then randomly splice one member from the copy and check for the required value:
function randomValueByChar(arr, c) {
var a = arr.slice && arr.slice();
var i = a.length || 0;
var t;
while (i--) {
t = a.splice(Math.random() * i | 0, 1);
if (t[0].Char.indexOf(c) != -1) return t;
}
}
Another approach is to create an array of the indexes (e.g. [0,1,2,3…]), then randomly splice one value at a time and use it as an index to retrieve a value from the array. Both approaches will not have an infinite loop and will visit each member a maximum of once.
I'm working on a website project and I have a paragraph containing a list of items (it would work great as a ul, but needs to stay a p) that needs to have the first letter of each item bold. I've created a function to do this:
function inserter(string, splitter, skip) {
var array = string.split(splitter);
var len = array.length;
for(var i = 1; i < len; i++) {
var a = array[i];
var b = '<b>';
var c = '</b>';
if(a.substr(0, 3) != skip){
array[i] = splitter + b + a.substr(0,1) + c + a.substr(1);
} else {
array[i] = splitter + a;
}
}
var strFix = array.join("");
return strFix;
}
$(function(){
var text = $(".caps").html();
text = inserter(text, ': '); //bold the item after ': '
text = inserter(text, ', ', 'and'); // now bold after the comma ', ' and the skip variable which matches first three letters so the last and doesn't get bold
text = inserter(text, ', and '); //now for the item after the last 'and'
$(".caps").html(text);
});
But it needs to be called and the string iterated for every different splitter (which could ruin performance on pages with more than a few of these), and I'm wondering how I could just call it once so all the splitters are looked at during one iteration?
Example page:
http://heidikratzke.com/about.php
When you see the page, you will see that I will be doing this on multiple paragraphs within a jQuery slideshow.
If it doesn't seem like this will be a performance hit for slower browsers, I'll leave it as is.
Appreciate any suggestions on how to do it better.
One optimization you could make is to use the splitter you use to split the string into an array to join the array once the operation is finished:
function inserter(string, splitter, skip) {
var array = string.split(splitter);
var len = array.length;
for(var i = 1; i < len; i++) {
var a = array[i];
var b = '<b>';
var c = '</b>';
if(a.substr(0, 3) != skip){
array[i] = b + a.substr(0,1) + c + a.substr(1);
} else {
array[i] = a;
}
}
return array.join(splitter);
}
There's probably more you could do here as well, but this jumped out at me.
further optimization
The following gets variable declaration out of the loop:
function inserter(string, splitter, skip) {
var array = string.split(splitter);
var len = array.length;
var i, a, b='<b>', c='</b>';
for(i = 1; i < len; i++) {
a = array[i];
if(a.substr(0, 3) != skip){
array[i] = b + a.substr(0,1) + c + a.substr(1);
} else {
array[i] = a;
}
}
return array.join(splitter);
}