Javascript: Reversing the loop ouput - javascript

Basically i'm creating a script to display the place value for set of numbers. Here's my script:
var arrn = '3252';
var temp = 0;
var q = arrn.length;
var j = 0;
for (var i = q-1; i >= 0; i--,j++) {
if (j!=0) temp = temp + ' + ';
{
temp += arrn[i] * Math.pow(10, j);
}
}
alert(temp);
My goal is to achieve 3000 + 200 + 50 + 2. But i get 2 + 50 + 200 + 3000. I tried temp.reverse() & sort functions but doesn't seem to work. Please help

Change
if(j!=0)temp=temp +' + ';
{
temp +=arrn[i]*Math.pow(10,j);
}
to
if(j!=0) {
temp=' + ' + temp;
}
temp = arrn[i]*Math.pow(10,j) + temp;
Live Example
Side note: Your braces in the first code block above are very misleading. What you have:
if(j!=0)temp=temp +' + ';
{
temp +=arrn[i]*Math.pow(10,j);
}
is
if(j!=0)temp=temp +' + ';
temp +=arrn[i]*Math.pow(10,j);
which is to say
if(j!=0) {
temp=temp +' + ';
}
temp +=arrn[i]*Math.pow(10,j);
the block in your version is not associated with the if, it's just a freestanding block.
Side note #2: Since you're using temp as a string everywhere else, I would initialize it with '' rather than with 0. Example The reason your string didn't end up with an extraneous 0 was really quite obscure. :-)

Just add the number to the beginning of the string instead of at the end:
for (var i = q - 1; i >= 0; i--, j++) {
if (j != 0) {
temp = ' + ' + temp;
}
temp = arrn[i] * Math.pow(10, j) + temp;
}
Demo: http://jsfiddle.net/Guffa/rh9oso3f/
Side note: You are using some confusing brackets in your code after the if statement. As there is a statement following the if statement, the brackets starting on the next line becomes just a code block, but it's easy to think that it's supposed to be the code that is executed when the condition in the if statement is true.
Another side note: the language attribute for the script tag was deprecated many years ago. Use type="text/javascript" if you want to specify the language.

How about temp.split("+").reverse().join(" + ")?

You can do this way. I know it can be optimised. But it works
var arrn='3252';
var temp=0;
var q=arrn.length;
var res = [];
var j=0;
for(var i=q-1;i>=0;i--,j++)
{
temp += parseFloat(arrn[i])*Math.pow(10,j);
res.push(arrn[i]*Math.pow(10,j));
}
res.reverse();
alert(res.join('+') + " = " + temp);
http://jsfiddle.net/he7p8y5m/

var arrn='3252';
var temp=new Array();
var q=arrn.length;
for(var i=0;i<=q-1; i++){
temp.push(arrn[i]*Math.pow(10,(q-i-1)));
}
temp = temp.join('+');
alert(temp);

Related

How to know when a for loop is done without knowing how many iterations there will be?

using a for-loop in javascript i´m getting a not known amount of id´s, they´re not in an array but coming one by one.
is there a way to get an alert when there are no more id´s to retrieve meaning the for loop is done?
i can´t wrap my head around this, any help would be greatly appreciated.
thanks!
edited with code for clarification.
function iterateDevices(api) {
var count = api.getcount("devices"); var apiPath = dequotePath(api);
for (var i = 0; i < count; i++) {
var deviceApi = new LiveAPI(apiPath + " devices " + i); if (deviceApi) {
var deviceName = deviceApi.get("name"); var deviceid = deviceApi.id; //var
deviceName = deviceApi.get("parameters"); var className =
deviceApi.get("class_name"); var deviceApiPath = dequotePath(deviceApi);
var chainsCount; var chainApi; var j;
if ((className == "DrumGroupDevice") || (className ==
"AudioEffectGroupDevice") || (className == "InstrumentGroupDevice")){
//post(deviceName + " id " + deviceid + "\'\n"); //outlet(0,deviceid);
// arr.push(deviceName);
if (deviceApi.get("can_have_chains") == 1) { chainsCount =
deviceApi.getcount("chains"); // only racks have chains for (j = 0; j
< chainsCount; j++) { // post("id" + deviceid + " found device " +
deviceName + " at path \'" + deviceApiPath + "\'\n");
//outlet(0,deviceid); chainApi = new LiveAPI(deviceApiPath + " chains
" + j); iterateDevices(chainApi);
myFunction(); } chainsCount = deviceApi.getcount("return_chains");
// only racks have chains for (j = 0; j < chainsCount; j++) {
//post("2 found device " + deviceName + "id"+deviceid + " at path
\'" + deviceApiPath + "\'\n"); // outlet(0,deviceid); chainApi = new
LiveAPI(deviceApiPath + " return_chains " + j);
iterateDevices(chainApi);
}
}
}
}
}
} iterateDevices.local = 1;
The purpose of a for loop is to deal with a known number of iterations. If you want to deal with an unknown number of iterations, you would use a while loop.
Of course, this is programming, so lets look at the crazy things we can do:
Iterate over a collection. We dont necessarily know how many things
are in the collection, but we may want to iterate over all of them.
The number of things in the collection might even change as we're
iterating.
We can change how we iterate through the loop. That whole i++ part?
What if we replace it with i += 2? Or what if it's i -=1? Or i += j
and j changes while we're iterating?
We can change how we break out of the loop. You can put a break
statement in there to break out of the loop anytime. You can also
change the conditional of the loop. What if i < 100 is replaced by
i<j? Or what if we replace it with i<100 || q == true?
You may use a while loop instead of a for and insert a condition to terminate the loop.
Using pseudo-code, you could do something like:
other_ids = True // boolean var
while(other_ids) {
// do what you have to do
other_ids = FuncionToCheckWhetherThereAreNewIds
}
FuncionToCheckWhetherThereAreNewIds should be a function that gives you true if there are new ids and false if there are not.

Copy string and increment version

For example if we have string str and I copy it it will be str_1, str_2, str_3 and so on..
If I copy str_2 then it will be str_2_1, str_2_2 and so on.
I have following logic but it does not work..
It should return 'Test2_5' (because Test2 AND Test2_4 already exists) but it returns 'Test2_4'
function createName(nameToCopy) {
var i;
var version = 1;
var nameCopiesArr = ["Test2", "Test2_2",
"Test2_3",
"Test2_4",
"Test2_2_2",
"Test2_3_1",
"Test2_2_1_2",
"Test2_2_3"
];
if (nameCopiesArr && nameCopiesArr.length > 1) {
for (i = 0; i < nameCopiesArr.length; i++) {
var indexes = nameCopiesArr[i].lastIndexOf('_') ? nameCopiesArr[i].match(/\d+$/) : 0
if (indexes) {
version = indexes[indexes.length - 1];
version = parseInt(version) + 1;
}
}
}
p = nameToCopy + '_' + version;
document.getElementById("demo").innerHTML = p;
return p;
}
<button onclick="createName('Test2')">Click me</button>
<p id="demo"></p>
You could search for all string which starts with the given name and a dash and an ending number. Then take the max number of ending and return the given string with an incremented version.
function createName(nameToCopy) {
var copies = ["Test2", "Test2_2", "Test2_3", "Test2_4", "Test2_2_2", "Test2_3_1", "Test2_2_1_2", "Test2_2_3"],
filtered = copies.filter(/./.test.bind(new RegExp(nameToCopy + '_' + '\\d+$'))),
version = filtered.reduce((v, s) => Math.max(v, +s.match(/\d+$/)[0]), 0);
return nameToCopy + '_' + ++version;
}
console.log(['Test2', 'Test', 'Test2_2'].map(createName));
More traditional
function createName(nameToCopy) {
var copies = ["Test2", "Test2_2", "Test2_3", "Test2_4", "Test2_2_2", "Test2_3_1", "Test2_2_1_2", "Test2_2_3"],
regexp = new RegExp(nameToCopy + '_' + '\\d+$'),
version = 0,
i, v;
for (i = 0; i < copies.length; i++) {
if (regexp.test(copies[i])) {
v = +copies[i].match(/\d+$/)[0];
if (v > version) {
version = v;
}
}
}
return nameToCopy + '_' + (version + 1);
}
console.log(['Test2', 'Test', 'Test2_2'].map(createName));
I update your code to test the number of the '_' char and if the current string contains the given input.
function createName(nameToCopy) {
var i;
var version = 1;
var nameToCopy_Nb = (nameToCopy.match(/_/g) || []).length; //number of the '_' char
var nameCopiesArr = ["Test2", "Test2_2",
"Test2_3",
"Test2_4",
"Test2_2_2",
"Test2_3_1",
"Test2_2_1_2",
"Test2_2_3"
];
if (nameCopiesArr && nameCopiesArr.length > 1) {
for (i = 0; i < nameCopiesArr.length; i++) {
var item_Nb = (nameCopiesArr[i].match(/_/g) || []).length;//number of the '_' char
if (nameCopiesArr[i].indexOf(nameToCopy) !== -1 && item_Nb === nameToCopy_Nb + 1) {
var indexes = nameCopiesArr[i].lastIndexOf('_') ? nameCopiesArr[i].match(/\d+$/) : 0
if (indexes) {
version = indexes[indexes.length - 1];
version = parseInt(version) + 1;
}
}
}
}
p = nameToCopy + '_' + version;
document.getElementById("demo").innerHTML = p;
return p;
}
But the answer of #Nina is good and probably the shortest !!! (I upvote her answer)
JSFiddle
I'm not sure what you're trying to do here, or why, so I can't really comment on your code. Just note that it is not too efficient, and not too understandable. And as a side note, your html doesn't call the code you wrote.
to answer your question of why it returns 'Test2_4' : your code loops through the hard coded values you put into the nameCopiesArr, and the version variable keeps the number of the current name + 1. And then you overwrite this with the result from the next entry in the array. Since the last entry in the array is 'Test2_2_3', you grab the last number there - which is 3 - and add 1 to that, so after your last iteration the version variable holds the value of 4 - and this is what you return.

javascript replace string/html from array

I try to create a system replacement for ToolTip.
I already create a version but its not quite optimal (search a better way to do it)
here's a fiddle : http://jsfiddle.net/forX/Lwgrug24/
I create a dictionary (array[key]->value). the array is order by length of the key.
each key is a word or an expression, the value is the definition of the expression.
So, I replace the expression by a span (could/should be a div). The span is used for the tooltip (I use the data-title as tooltip text).
because some word is reused in expression, I need to remove expression already with tooltip (in real life think of father/grandfather, you dont want the definition of father inside grandfather). For replacement I use a ramdom value. That's the worst of this code.
You could make comment or post a new way to do it. maybe someone already did it.
Clarification :
I think my way to do it is wrong by using a string for replacement. Or it could be more secure. How should I do it?
html :
<div class="container">
one two three four five six seven eight nine ten
</div>
javascript :
$(function() {
var list = [
{'k':'one two three four five','v':'First five number.'},
{'k':'four five six seven','v':'middle number.'},
{'k':'six seven eight','v':'second middle number.'},
{'k':'two','v':'number two.'},
{'k':'six','v':'number six.'},
{'k':'ten','v':'number ten.'}
];
$(".container").each(function(){
var replacement = new Array();
for (i = 0; i < list.length; i++) {
var val = list[i];
var rString = randomString(32, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
replacement[rString + "_k"] = htmlEncode(val["k"]);
replacement[rString + "_v"] = htmlEncode(val["v"]);
var re = new RegExp("(" + val["k"] + ")","g");
$(":contains('" + val["k"] + "')",$(this).parent()).html(function(_, html) {
var newItem = '<span class="itemWithDescription" '
+ 'data-title="' + rString + "_v" + '">'
+ rString + "_k"
+ '</span>';
return html.replace(re, newItem);
});
}
for (var k in replacement){
$(this).html($(this).html().replace(k,replacement[k]));
console.log("Key is " + k + ", value is : " + replacement[k]);
}
});
$(document).tooltip({
items:'.itemWithDescription',
tooltipClass:'Tip',
content: function(){
var title = $(this).attr("data-title");
if (title == ""){
title = $(this).attr("title"); //custom tooltips
}
return title;
}
});
});
function randomString(length, chars) {
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.round(Math.random() * (chars.length - 1))];
return result;
}
function htmlEncode(value){
//create a in-memory div, set it's inner text(which jQuery automatically encodes)
//then grab the encoded contents back out. The div never exists on the page.
return $('<div/>').text(value).html();
}
I added a little thing. on the random function, I put a | and } for every char, its bigger but there's not much chance to have a conflic with an expression.
for (var i = length; i > 0; --i) result += '|' + ( chars[Math.round(Math.random() * (chars.length - 1))] ) + '}' ;
http://jsfiddle.net/forX/Lwgrug24/3/

Working on script in google-apps-script, any suggestions?

Problem: I am creating an array, or multiple arrays, to write values, and continue doing so until a certain value is drawn. The long view for this code is to, using these values to match one letter to another. (i.e. The Bombe used in WWII.) Except this will be completely digital. The Bombe was a decrypter that find that one letter is able to get mapped to another. (Enigma example will be posted in comments.) I am trying to decrpyt any message using this.
Understanding: I don't remember a lot of code especially since I have never used google-apps-script before. I no basic ideas, but some of the syntax's are different I am getting lost. (i.e.: instead of System.out.print(); it would be Logger.log(data);. That's really all I have gotten from it so far. I have some code worked out which can be found here.
Background: This is quite a lot of text to read I understand, but hear me out before you just flag me and move on. The hyperlink posted in the above comment under the words "Enigma example" shows the mapping that I am trying to do in reverse. I however need to create loops and variables that I do not remember how to create. I have information on the Enigma and Bombe: Enigma & Bombe info. I have done some searches on Google and the like, however nothing that I understand or benefit my end goal. All I have gotten is another link, which I will post in the comments, that shows me a basic loop as they put it.
What I need help with: I am asking for help in the following: Looping, variables and arrays. Suggestions will be the most valuable to me, because I am here to learn, not get my stuff done done by asking.
Ideas: Some ideas I have are, Garbage collectors, multi-dimensional array and/or just a sequence of possibilities. (See the "Enigma & Bombe info" link above.
For easy Copy/Pasting:
function bombeCode1() {
var fastRotor = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N",
"O","P","Q","R","S","T","U","V","W","X","Y","Z"];
var mediumRotor = fastRotor;
var slowRotor = fastRotor;
var rows = 26;
var columns = 26;
for (var i=0; i < rows ; i++) {
Logger.log('Outer Loop: value of i : ' + i);
// Logger.log("Partition for Outer Loop");
// Logger.log(" ");
var fastRotorValue = fastRotor[i];
for (var j=0; j < columns ; j++) {
Logger.log('-Inner Loop value of j : ' +j);
//var fastRotorValue = fastRotor[i];
var medRotorValue = mediumRotor[j];
// Logger.log("---- " + fastRotorValue + " " + medRotorValue);
for (var k=0; k < 26 ; k++) {
// Logger.log('---- XXXX Third Loop value of k : ' + k);
//var fastRotorValue = fastRotor[i];
//var medRotorValue = mediumRotor[j];
var slowRotorValue = slowRotor[k];
Logger.log("---- XXXX " + fastRotorValue + " " + medRotorValue + " " + slowRotorValue);
}; //var objectNumberValuePair = {"0":"A", "1":"B", "2":"C","3":"D","4":"E","5":"F","6":"G","7":"H","8":"I",
// "9":"J","10":"K","11":"L","12":"M","13":"N","14":"O","15":"P","16":"Q","17":"R",
// "18":"S","19":"T","20":"U","21":"V","22":"W","23":"X","24":"Y","25":"Z"}
// Logger.log(slowRotorValue = objectNumberValuePair);
// Logger.log(medRoterValue = objectNumberValuePair);
// Logger.log(fastRoterValue = objectNumberValuePair);
}
}
}
Here is the code I modified a little bit, just to show the Loop values in the Logger print out.
function bombeCode1() {
var fastRotor = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N",
"O","P","Q","R","S","T","U","V","W","X","Y","Z"];
var mediumRotor = fastRotor;
var slowRotor = fastRotor;
var rows = 3;
var columns = 6;
for (var i=0; i < rows ; i++) {
Logger.log('Outer Loop: value of i : ' + i);
Logger.log("Partition for Outer Loop");
Logger.log(" ");
for (var j=0; j < columns ; j++) {
Logger.log('----Inner Loop value of j : ' + j);
var fastRoterValue = fastRotor[i];
var medRoterValue = mediumRotor[j];
Logger.log("---- " + fastRoterValue + " " + medRoterValue);
for (var k=0; k < 6 ; k++) {
Logger.log('---- XXXX Third Loop value of k : ' + k);
var fastRoterValue = fastRotor[i];
var medRoterValue = mediumRotor[j];
var slowRotorValue = slowRotor[k];
Logger.log("---- XXXX " + fastRoterValue + " " + medRoterValue + " " + slowRotorValue);
};
}
}
}
Run it and see what you think. I'm sure it's not what you need, but got to start somewhere.

Highlighting string at multiple occurrences

I'm currently implementing a substring search. From the algorithm, I get array of substrings occurence positions where each element is in the form of [startPos, endPos].
For example (in javascript array):
[[1,3], [8,10], [15,18]]
And the string to highlight is:
ACGATCGATCGGATCGAGCGATCGAGCGATCGAT
I want to highlight (in HTML using <b>) the original string, so it will highlight or bold the string from position 1 to 3, then 8 to 10, then 15 to 18, etc (0-indexed).
A<b>CGA</b>TCGA<b>TCG</b>GATC<b>GAGC</b>GATCGAGCGATCGAT
This is what I have tried (JavaScript):
function hilightAtPositions(text, posArray) {
var startPos, endPos;
var startTag = "<b>";
var endTag = "</b>";
var hilightedText = "";
for (var i = 0; i < posArray.length; i++) {
startPos = posArray[i][0];
endPos = posArray[i][1];
hilightedText = [text.slice(0, startPos), startTag, text.slice(startPos, endPos), endTag, text.slice(endPos)].join('');
}
return hilightedText;
}
But it highlights just a range from the posArray (and I know it is still incorrect yet). So, how can I highlight a string given multiple occurrences position?
Looking at this question, and following John3136's suggestion of going from tail to head, you could do:
String.prototype.splice = function( idx, rem, s ) {
return (this.slice(0,idx) + s + this.slice(idx + Math.abs(rem)));
};
function hilightAtPositions(text, posArray) {
var startPos, endPos;
posArray = posArray.sort(function(a,b){ return a[0] - b[0];});
for (var i = posArray.length-1; i >= 0; i--) {
startPos = posArray[i][0];
endPos = posArray[i][1];
text= text.splice(endPos, 0, "</b>");
text= text.splice(startPos, 0, "<b>");
}
return text;
}
Note that in your code, you are overwriting hilightedText with each iteration, losing your changes.
Try this:
var stringToHighlight = "ACGATCGATCGGATCGAGCGATCGAGCGATCGAT";
var highlightPositions = [[1,3], [8,10], [15,18]];
var lengthDelta = 0;
for (var highlight in highlightPositions) {
var start = highlightPositions[highlight][0] + lengthDelta;
var end = highlightPositions[highlight][1] + lengthDelta;
var first = stringToHighlight.substring(0, start);
var second = stringToHighlight.substring(start, end + 1);
var third = stringToHighlight.substring(end + 1);
stringToHighlight = first + "<b>" + second + "</b>" + third;
lengthDelta += ("<b></b>").length;
}
alert(stringToHighlight);
Demo: http://jsfiddle.net/kPkk3/
Assuming that you're trying to highlight search terms or something like that. Why not replace the term with the bolding?
example:
term: abc
var text = 'abcdefgabcqq';
var term = 'abc';
text.replace(term, '<b>' + term + '</b>');
This would allow you to avoid worrying about positions, assuming that you are trying to highlight a specific string.
Assuming your list of segments is ordered from lowest start to highest, try doing your array from last to first.
That way you are not changing parts of the string you haven't reached yet.
Just change the loop to:
for (var i = posArray.length-1; i >=0; i--) {
If you want to check for multiple string matches and highlight them, this code snippet works.
function highlightMatch(text, matchString) {
let textArr = text.split(' ');
let returnArr = [];
for(let i=0; i<textArr.length; i++) {
let subStrMatch = textArr[i].toLowerCase().indexOf(matchString.toLowerCase());
if(subStrMatch !== -1) {
let subStr = textArr[i].split('');
let subStrReturn = [];
for(let j=0 ;j<subStr.length; j++) {
if(j === subStrMatch) {
subStrReturn.push('<strong>' + subStr[j]);
} else if (j === subStrMatch + (matchString.length-1)){
subStrReturn.push(subStr[j] + '<strong>');
} else {
subStrReturn.push(subStr[j]);
}
}
returnArr.push(subStrReturn.join(''));
} else {
returnArr.push(textArr[i]);
}
}
return returnArr;
}
highlightMatch('Multi Test returns multiple results', 'multi');
=> (5) ['<strong>Multi<strong>', 'Test', 'returns', '<strong>multi<strong>ple', 'results']

Categories