I have this code :
function list(target, letters, lvls) {
var index = 0;
(function iter(s, lvl) {
if(lvl++ == lvls)
return target.appendChild(document.createTextNode(
++index + ' - ' + s + '\n'
));
for(var i=0; i<letters.length; ++i)
iter(s + letters[i], lvl);
})('', 0);
}
list(document.getElementById('output'), 'abc', 3);
But I don't know this type of function syntax.
Can some one explain to me the function behavior and what this code exactly do step by step.
And thanks in advance
This seems to be iterating through the string 'abc' and creating as many X letter strings as possible with the combination of all the characters in the string.
So the call is list([element ID to output strings], [string of all possible letters], [size of strings to generate])
So the following example -
<script type="text/javascript">
function list(target, letters, lvls) {
var index = 0;
(function iter(s, lvl) {
if(lvl++ == lvls)
return target.appendChild(document.createTextNode(
++index + ' - ' + s + '\n'
));
for(var i=0; i<letters.length; ++i)
iter(s + letters[i], lvl);
})('', 0);
}
list(document.getElementById('output'), 'ab', 2);
</script>
<div id="output"></div>
will output all possible two letter strings (defined by param 3), using the characters from the input string (param 2) and will result in -
1 - aa 2 - ab 3 - ba 4 - bb
Explanation
Inside the method there is a second called iter with the arguments s and lvls. On
first run, the arguments parsed to the iter method are blank and 0. It hits the for
loop which runs until all of the letters in the string letters have been used up,
each time recursively calling the iter method. Each time it adds the current letter in
the iteration s, along with the next letter in the string letters[i]. Every time it
recursively calls itself it builds up the string until the number of specified levels have
been reached for that particular string and then returns the result, along with the index
value. This is just a numeric value to represent the string count.
Related
(I did ask a similar question in the past, but the documentation was wrong, so this is the correct version of that past question)
Please help me in JavaScript: The program that I am coding is one that takes in an expression in prefix notation and outputs the same expression in infix notation. The idea behind this program is as follows:
if the user enters + 1 2 the expected output is 1 + 2. All valid symbols are +, -, *, /, and %. The amount of numbers that the user can enter should be limitless (so for example, if I enter + + + + + + + + + 1 2 3 4 5 6 7 8 9 10, the program should return 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10).
Could someone please help me fill in the comment out portion of the loop, and if you think there's a better approach to the problem entirely, I am open to that!
function infix(input) {
var x = input.split(''); // splits each variable and stores it in an array
var output = [];
var final = " "; // will be used to store our infix expression
for (var i = 0; i < x.length; i++) {
//if x[i] is any of the following : "+, -, *, /, or %" , store it in array output at index 0
//else if x[i] is a number : store it in an index of array output that is >= 1
}
for (var j = 0; j < output.length; j++) {
var final = x[0] + x[j];
}
console.log(final);
}
infix("1 + 2 + 3") // should output "+ + 1 2 3"
infix("1 - 2 % 3 + 1 * 4") // should output "- % + * 1 2 3 1 4"
Your code is mostly there.
The main logic of your program needs to split your input string into two sections (arrays). One for symbols/operands, and another for numbers. Checking if x[i] is "+, -, ..." will allow us to check if the current symbol is an operand, which is a good start. However, we don't want to store it at index 0 of the output array. If you did this, then all of the symbols would be inputted in reverse order (which isn't what you want). Instead, you can add your symbols to the end of your array. In the code snippet below, I have pushed all symbols into the operands array.
So, how can we check if x[i] is a symbol? One way is to check x[i] against every symbol like so:
if(x[i] === "+" || x[i] === "-" || ... ) {
operands.push(x[i]); // add the symbol to the end of the array
}
Or, you could write this a little more cleanly using .includes(), which removes the need to multiple ||:
var symbols = ['+', '-', '*', '/', '%'];
...
if(symbols.includes(x[i])) {
operands.push(x[i]);
}
If the current character (x[i]) isn't a symbol then it must be a number (as we split on spaces). So, you can then add an else, and push the current character into the numbers array.
After you've looped through all characters, you'll have an array of operands, in the order that they appeared in the input string, and an array of numbers, also in the order they appeared in the input string. Our last step is to convert the operands and numbers array into strings, where each element in these arrays are separated by a space. The easiest way to do this is by using the .join() method, which will join every element in your array into a string, separating each element by the argument you give it.
By doing all of this, you can get your desired output:
function infix(input) {
var x = input.split(' '); // splits each character and stores it in an array
var operands = [];
var numbers = [];
var symbols = ['+', '-', '/', '*', '%'];
for (var i = 0; i < x.length; i++) {
if(symbols.includes(x[i])) {
operands.push(x[i]);
} else {
numbers.push(x[i]);
}
}
var final = operands.join(' ') +' ' +numbers.join(' ');
return final;
}
console.log(infix("1 + 2 + 3")); // "+ + 1 2 3"
console.log(infix("1 - 2 % 3 + 1 * 4")); // "- % + * 1 2 3 1 4"
Or, you can do this more concisely by using the .match() method to get the non-numeric (or space) characters and another to get the numeric characters:
const infix = input =>
[...input.match(/[^\d\s]/g), ...input.match(/\d+/g)].join(' ');
console.log(infix("1 + 2 + 3")); // "+ + 1 2 3"
console.log(infix("1 - 2 % 3 + 1 * 4")); // "- % + * 1 2 3 1 4"
For some reason, my indexOf 2nd arg (where to start the search) is not working. It just always returns 4 or -1.
Where string test = "Bob jr" and I am using built-in JavaScript console on about:blank:
> var test = "Bob jr";
> test.indexOf('j', 0);
< 4 = $3
> test.indexOf('j', 1);
< 4 = $3
> test.indexOf('j', 12);
< -1 = $2
Why is this not working and how can I get it working?
Whether you start looking at 0 or index 1, the j is still at index 4.
Your final example proves the argument does work, because you said to start after the j (beyond the end of the string entirely), and sure enough, it didn't find it.
Let's see indexOf's second argument in action:
var str = "j and j and j x";
console.log("Search string: '" + str + "'");
for (var n = 0; n < str.length; ++n) {
test(str, n);
}
function test(s, start) {
var index = s.indexOf("j", start);
console.log("Starting at " + start + ": " + index);
}
If you want to find out how far after the index you've given it is to the j, you can do that in two ways:
Subtract your index from the result you get:
console.log("Distance: " + (test.indexOf('j', 1) - 1));
Search a substring:
console.log("Distance: " + test.substring(1).indexOf('j');
Check the documentation of indexOf here
str.indexOf(searchValue[, fromIndex])
There is no j after position 12 and that is why you are getting -1 in the last case.
indexOf always return the index within the calling String object of the first occurrence of the specified value, starting the search at fromIndex. The reason your return value isn't changing is because "j" is still the 5th character in your string, regardless of whether you begin your search a few characters into the string.
$('.creditCardText').keyup(function() {
var foo = $(this).val().split("-").join(""); // remove hyphens
if (foo.length > 0) {
foo = foo.match(new RegExp('.{1,4}', 'g')).join("-");
}
$(this).val(foo);
});
I found this tutorial on putting dash after every 4 character from here my question is what if the character interval is not constant like in this example it is only after every 4 what if the interval is 3 characters "-" 2 characters "-" 4 characters "-" 3 characters "-" so it would appear like this 123-12-1234-123-123.
In this case, it is more convenient to just write normal code to solve the problem:
function format(input, format, sep) {
var output = "";
var idx = 0;
for (var i = 0; i < format.length && idx < input.length; i++) {
output += input.substr(idx, format[i]);
if (idx + format[i] < input.length) output += sep;
idx += format[i];
}
output += input.substr(idx);
return output;
}
Sample usage:
function format(input, format, sep) {
var output = "";
var idx = 0;
for (var i = 0; i < format.length && idx < input.length; i++) {
output += input.substr(idx, format[i]);
if (idx + format[i] < input.length) output += sep;
idx += format[i];
}
output += input.substr(idx);
return output;
}
$('.creditCardText').keyup(function() {
var foo = $(this).val().replace(/-/g, ""); // remove hyphens
// You may want to remove all non-digits here
// var foo = $(this).val().replace(/\D/g, "");
if (foo.length > 0) {
foo = format(foo, [3, 2, 4, 3, 3], "-");
}
$(this).val(foo);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input class="creditCardText" />
While it is possible to do partial matching and capturing with regex, the replacement has to be done with a replacement function. In the replacment function, we need to determine how many capturing group actually captures some text. Since there is no clean solution with regex, I write a more general function as shown above.
You can split it using a regular expression. In this case, I'm using a expression to check for non-spaces with interval 3-2-4-3.
The RegExp.exec will return with a "match" array, with the first element containing the actual string. After removing the first element of the match, you can then join them up with dashes.
var mystring = "123121234123"
var myRegexp = /^([^\s]{3})([^\s]{2})([^\s]{4})([^\s]{3})$/g
var match = myRegexp.exec(mystring);
if (match)
{
match.shift();
mystring = match.join("-")
console.log(mystring)
}
Per further comments, the op clarified they need a fixed interval for when to insert dashes. In that case, there are several ways to implement it; I think regular expression would probably be the worst, in other words, overkill and overly complication solution.
Some simpler options would be to create a new character array, and in a loop append character by character, adding a dash too every time you get to the index you want. This would probably be the easiest to write and grok after the fact, but a little more verbose.
Or you could convert to a character array and use an 'insert into array at index'-type function like splice() (see Insert Item into Array at a Specific Index or Inserting string at position x of another string for some examples).
Pass the input value and the indexes to append the separator, first, it will remove the existing separators then just append separators on positions indexes.
export function addSeparators(
input: string,
positions: number[],
separator: string
): string {
const inputValue = input.replace(/-/g, '').split(''); // remove existing separators and split characters into array
for (let i = 0; i < inputValue.length; i++) {
if (positions.includes(i)) inputValue.splice(i, 0, separator);
}
return inputValue.join('');
}
The Collada file format contains lots of data which is stored as whitespace delimited list of float/int/boolean values. These lists can be huge. We parse these lists in JavaScript using roughly the following code:
var floats = input.split(' ').map(parseFloat)
But this generates a lot of garbage because the huge input string is split into thousands of individual small strings. Is there a way to avoid that? Something like a parseFloat() function which I can point at a offset within an existing string, and so avoid generating the garbage.
If you prefix your string with one space, you can use this to get the first number out of the string:
var start = 0 // Initial search offset.
var firstOccurence = input.indexOf(' ', start);
//Get the substring from the first occurrence of ' ' after start, to the next one, and parse it as a float.
parseFloat(input.substring(firstOccurence , input.indexOf(' ', firstOccurence+1)));
Then, you can use the following to get the numbers after that, out of the string:
firstOccurence = t.indexOf(' ', firstOccurence+1);
parseFloat(t.substring(firstOccurence , t.indexOf(' ', firstOccurence+1)));
Using this in a loop, you can search through your list, and you can start searching the list at a specified index. You can't however, ask for the 7th float in the list, for example. The only reliable way to do that is to use .split(' '), or to use the above code in a loop.
To find the nth float in the input, you can use the following:
for(var i = 0, previousIndex = 0; i < n; i++){
previousIndex = input.indexOf(' ', previousIndex + 1);
}
var float = parseFloat(input.substring(previousIndex, input.indexOf(' ', previousIndex + 1)));
This function can handle multiple white spaces as well as input that does not parse as a float.
input = "123 123 123 foo", start = 0, end = 0, result = [], num;
// empty string evaluates to false
while( end < input.length ) {
end = input.indexOf(" ", start );
// -1 => only one element in input || end of the string has been reached
if( end === -1 ) { end = input.length }
num = parseFloat( input.substring( start, end ) );
// Should extracted string fail to parse then skip
if( num ) result.push( num );
// move forward or end will match current empty space
start = end + 1;
}
result[2] // => "123";
Fiddle here
UPDATE
Just had a brainwave. Don't use the map function but just use the array created by splitting the string like so:
var floats = input.split(' ');
for( var i = 0, len = input.length; i < len; i++ ) {
input[i] = parseFloat( input[i] );
}
How about this?
parseFloat(input.substring(5,10));
Where 5,10 are the starting and ending offsets of your desired chunk of string.
I have string looking like this:
01
02
03
99
I'd like to parse these to make them into strings like:
1. 2. 3. 99. etc.
The numbers are a maximum of 2 characters. Also I have to parse some more numbers later in the source string so I would like to learn the substring equivalent in javascript. Can someone give me advice on how I can do. Previously I had been doing it in C# with the following:
int.Parse(RowKey.Substring(0, 2)).ToString() + "."
Thanks
Why, parseInt of course.
// Add 2 until end of string
var originalA = "01020399";
for (var i = 0; i < originalA.length; i += 2)
{
document.write(parseInt(originalA.substr(i, 2), 10) + ". ");
}
// Split on carriage returns
var originalB = "01\n02\n03\n99";
var strArrayB = originalB.split("\n");
for (var i = 0; i < strArrayB.length; i++)
{
document.write(parseInt(strArrayB[i], 10) + ". ");
}
// Replace the leading zero with regular expressions
var originalC = "01\n02\n03\n99";
var strArrayC = originalC.split("\n");
var regExpC = /^0/;
for (var i = 0; i < strArrayC.length; i++)
{
document.write(strArrayC[i].replace(regExpC, "") + ". ");
}
The other notes are that JavaScript is weakly typed, so "a" + 1 returns "a1". Additionally, for substrings you can choose between substring(start, end) and substr(start, length). If you're just trying to pull a single character, "abcdefg"[2] will return "c" (zero-based index, so 2 means the third character). You usually won't have to worry about type-casting when it comes to simple numbers or letters.
http://jsfiddle.net/mbwt4/3/
use parseInt function.
parseInt(09) //this will give you 9
var myString = parseInt("09").toString()+". "+parseInt("08").toString();
string = '01\n02\n03\n99';
array = string.split('\n');
string2 = '';
for (i = 0; i < array.length; i++) {
array[i] = parseInt(array[i]);
string2 += array[i] + '. ';
}
document.write(string2);
var number = parseFloat('0099');
Demo
Substring in JavaScript works like this:
string.substring(from, to);
where from is inclusive and to is exclusive. You can also use slice:
string.slice(from, to)
where from is inclusive and to is exclusive. The difference between slice and substring is with slice you can specify negative numbers. For example, from = -1 indicates the last character. from(-1, -3) would give you the last 2 characters of the string.
With both methods if you don't specify end then you will get all the characters to the end.
Paul
Ii they are always 2 digits how about;
var s = "01020399";
var result = []
for (var i = 0; i < s.length; i+=2)
result.push(parseInt(s.substr(i, 2), 10) + ".")
alert( result[2] ) // 3.
alert( result.join(" ") ) // 1. 2. 3. 99.