I have a text field represented as: field = {text: "", valid: false}, and an input with [(ngModel)]="field.text".
I want to make that field only accept a defined set of characters (for this issue, numbers), and doing (keypress) doesn't work on mobile, so I did: (ngModelChange)="fieldChanged(field)"
The method does the following:
fieldChanged(field) {
console.log(field.text);
field.text = Array.from(field.text).filter((char:string) => "0123456789".indexOf(char) != -1).join("");
console.log(field.text);
}
And it's behaviour is extremely weird.
Legend:
- input: what key was pressed
- before update: first console.log
- after update: second console.log
- output: what I see on screen in the input
| input | before update | after update | output |
|---------|---------------|--------------|--------|
| "" | "" | "" | "" | <- starting position, no event
| "a" | "a" | "" | "a" |
| "a" | "aa" | "" | "aa" |
| "4" | "aa4" | "4" | "4" |
| "a" | "4a" | "4" | "4a" |
| "a" | "4aa" | "4" | "4aa" |
| "4" | "4aa4" | "44" | "44" |
Why does it always update the output when I enter a legal character? It should be working for each event call.
Edit:
Plunker
I think the cause is that modifying the value on ngModelChange breaks change detection, for example if you change the value back to the previous value, because an invalid character was added.
A workaround:
constructor(private cdRef:ChangeDetectorRef) {}
fieldChanged(field) {
console.log(field.text);
field.text = Array.from(field.text).filter((char:string) => "0123456789".indexOf(char) != -1).join("");
console.log(field.text);
var tmp = field.text;
field.text = null; // or some other value that normally won't ever be in `field.text`
this.cdRef.detectChanges();
field.text = tmp;
this.cdRef.detectChanges(); // I guess this 2nd call won't be necessary
}
If anyone having the issues in updating the value, use setTimeout function while updating
// setTimeout function
setTimeout(() => {
field.text = temp;
this.cdRef.detectChanges();
}, 1);
Related
I was developing a minesweeper game in typescript. But while defining a type named Cell, I encountered an error.
Code:
Not Working
const bomb = "💣";
const flag = "🚩";
export type Cell = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | bomb | flag;
export type Board = Array<Array<Cell>>;
While defining type Cell the error raises:
'bomb' refers to a value, but is being used as a type here. Did you mean 'typeof bomb'?ts(2749)
while doing it in another way without any variable or constant works:
Fine
export type Cell = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | "💣" | "🚩";
What am I doing wrong? What is the reason?
bomb and flag and not types.
The typeof operator will give you access to the type of a value.
const bomb = "💣";
const flag = "🚩";
export type Cell = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | typeof bomb | typeof flag;
In trying to solve the following problem:
Generate all combinations of an array of string.
Ex: Input: ['A', 'T', 'C', 'K']
Output: [
'ATCK', 'ATC', 'ATK',
'AT', 'ACK', 'AC',
'AK', 'A', 'TCK',
'TC', 'TK', 'T',
'CK', 'C', 'K',
''
]
I have the following code:
function getSpellableWords(arr) {
const res = [];
// helper(arr, res, 0, '');
helper(arr, res, 0, []);
return res;
}
function helper(arr, res, i, slate) {
const char = arr[i];
console.log(i, 'i')
if(i === arr.length) {
res.push(slate.join(''));
return;
}
// slate = slate + char;
slate.push(char)
console.log(slate, 'slate')
helper(arr, res, i+1, slate);
slate.pop()
helper(arr, res, i+1, slate);
}
getSpellableWords(['A', 'T', 'C', 'K']);
My questions is:
If I remove the following lines in the code:
helper(arr, res, i+1, slate);
Once i is equal to 5 (which is the array.length), the code will stop after it pushes slate into res. However, if I leave that line in, a call stack is set up and so i will go up from 1->5, then pop out gradually to 4 then 3 then back to 4 and so on. Why does that happen?
Clarification: So I understand that for each recursion call, another i variable is generated. However, I was expecting the second recursion call to also generate i from 1->4 again, but this time instead of incrementing it linearly, there's backtracking going on as well. Why wasn't there backtracking in the first call, and why does the second call generate the rest of the results when the first call only generates the first result?
Each recursive call of helper will indeed add a level on the call stack, so that when a recursive call returns back to its caller, that calling code can continue with its own local execution context.
Each execution of helper has its own execution context, which includes a local variable i which is only visible to that execution context. It only plays a role at that level in the call stack.
Note that the helper code never changes the value of its i variable. It gets initialised with whatever value is passed as third argument when it gets called, and that is the only value it will ever have.
The change to i that you notice is in fact no change. Every different value you see for i is in fact about a different variable that just happens to have the same name.
Here is a little schema on the life of these i variables for when the res variable has length 2 (just to not make it too lengthy!):
helper(arr, res, 0, []); // The initial call
+--------top level helper execution context----+
| i = 0 |
| .... |
| slate.push(char) |
| helper(arr, res, i+1, slate); |
| +---nested helper execution context---+ |
| | i = 1 | |
| | .... | |
| | slate.push(char) | |
| | helper(arr, res, i+1, slate); | |
| | +--deepest exec. context-----+ | |
| | | i = 2 | | |
| | | ... | | |
| | | res.push(slate.join('')); | | |
| | | return; | | |
| | +----------------------------+ | |
| | // i is still 1 | |
| | slate.pop() | |
| | helper(arr, res, i+1, slate); | |
| | +----------------------------+ | |
| | | i = 2 | | |
| | | ... | | |
| | | res.push(slate.join('')); | | |
| | | return; | | |
| | +----------------------------+ | |
| | // i is still 1 | |
| +-------------------------------------+ |
| // i is still 0 |
| slate.pop() |
| helper(arr, res, i+1, slate); |
| +-------------------------------------+ |
| | i = 1 | |
| | .... | |
| | slate.push(char) | |
| | helper(arr, res, i+1, slate); | |
| | +----------------------------+ | |
| | | i = 2 | | |
| | | ... | | |
| | | res.push(slate.join('')); | | |
| | | return; | | |
| | +----------------------------+ | |
| | // i is still 1 | |
| | slate.pop() | |
| | helper(arr, res, i+1, slate); | |
| | +----------------------------+ | |
| | | i = 2 | | |
| | | ... | | |
| | | res.push(slate.join('')); | | |
| | | return; | | |
| | +----------------------------+ | |
| | // i is still 1 | |
| +-------------------------------------+ |
| // i is still 0 |
+----------------------------------------------+
So we see that, in this particular algorithm, the size of the call stack (i.e. the depth of the recursion tree) corresponds exactly to the value of the variable i in the current execution context. When a function returns, the size of the call stack is reduced (i.e. the recursion depth decreased), and so we arrive in a state (popped from the stack) where there is another instance of i that also has a value that matches the now current size of the call stack.
Trincot gave a helpful detailed response on how that function works internally. I'd just like to point out a significant simplification you could write:
const getSpellableWords = ([x, ...xs]) =>
x == undefined
? ['']
: ((ps = getSpellableWords (xs)) => [...ps .map (p => x + p), ...ps]) ()
console .log (
getSpellableWords (['A', 'T', 'C', 'K'])
)
.as-console-wrapper {max-height: 100% !important; top: 0}
Here we note that the words we can make either include the first character or they don't. We can recursively calculate all the words from the remainder and then return the result of combining that array of words with those ones found by prepending the first character to each. And of course our recursion bottoms out if there are no characters left, in which our array returned contains only the empty string.
There is a slight bit of syntactic trickery here, with an IIFE in the recursive branch. We might prefer to use a call helper function, which takes a function and any arguments and calls that function with those arguments. Sometimes that's clearer:
const call = (fn, ...args) => fn (...args)
const getSpellableWords = ([x, ...xs]) =>
x == undefined
? ['']
: call (
(ps) => [...ps .map (p => x + p), ...ps],
getSpellableWords (xs)
)
I am working in Google sheets
I have a find and replace function gotten from here. It works great when the array is made from a single column of data
But, in certain instances in which I want to use my function I have all my data sitting in an array which is being passed from prior processing, the data if printed to the page looks like
| Id | Segment |Other Column| etc..
|----|--------------------|------------|
| 1 | AAA AA|AA|CaaL AA |stuff |
| 2 | AAA-AA|AA|CaaL |stuff |
| 3 | AAA, AA|AA|AA |AA |
| 4 | AA |stuff |
| 5 | AA AA | |
| 6 | AA, AA |AA |
| 7 | |stuff |
| 8 | CaaL |stuff |
| 9 | AA |stuff |
I only want to replace data in the Segment column
| Id | Segment ||Other Column| etc..
|----|-------------------|------------|
| 1 | AAA AA|zz|CaaL AA |stuff |
| 2 | AAA-AA|zz|Bob |stuff |
| 3 | AAA, AA|zz|zz |AA |
| 4 | zz |stuff |
| 5 | AA AA | |
| 6 | AA, AA |AA |
| 7 | |stuff |
| 8 | Bob |stuff |
| 9 | zz |stuff |
As it is the AA in the Other Column (could be in any column, I have no way of knowing) is being replaced which I do not want
Can the findReplace function be restricted to a single column in values updating that only that column in values ?
I have tried getting the column array I want to restrict values to with
function getColumn(matrix, col, startrow){
var column = [];
for(var i=startrow; i<matrix.length; i++){
column.push(matrix[i][col]);
}
return column;
}
and then attempting to restrict the input to this column
function fr(input) {
const aCOL = getColumn(values,2,0)
return input.aCOL.map(c => c.replace(regex, (x) => map[x]));
AND
return input.map(c => c.aCOL.map(y => y.replace(regex, (x) => map[x])));
}
I get Cannot read property 'map' of undefined
Thanks
function findReplace(values) {
var search_for = ["AA", "Caal"];
var replace_with = ["zz", "yy"];
var map = {};
search_for.forEach(function(item, i) {
map[item] = replace_with[i];
});
//map = { AA: 'zz', Caal: 'yy' };
const regex = new RegExp("(?<![^|])(?:" + search_for.join("|") + ")(?![^|])", "g");
range.setValues(values.map(fr));
function fr(input) {
return input.map(c => c.replace(regex, (x) => map[x]));
}
}
The code you got from your previous question works fine if you just change the range you're retrieving. So instead of creating a function to extract the column into an array, you can just adjust the range.
If the column you want to replace ('Segment') is the second one, then you can do the following changes.
From:
const col = ss.getRange(2, 3, ss.getLastRow()).getValues();
...
ss.getRange(2, 3, ss.getLastRow()).setValues(col.map(fr));
To:
const col = ss.getRange(2, 2, ss.getLastRow()).getValues();
...
ss.getRange(2, 2, ss.getLastRow()).setValues(col.map(fr));
How can I get substring dynamically, I want to split one word into two parts one is a string and other to no,
AA112 this is my string so from sql query
SELECT substr(thisColumn, 1,2) AS String from thisTable
I am getting AA in the query the index(2) I am pasing is dynamic I am getting from some value, So here I am able to get the string now I want to get the number +1 like it is 112 then -> 113
I have tried several queries but it is not working, I have tried doing it with javascript substring but it didn't work out.
Sample output
AAA123 -> AAA and 124
AA4 -> AA and 5
BBBB8 -> BBBB and 9
const input="AA112";
var numberPattern = /\d+/g;
const number = input.match(numberPattern)[0];
const text = input.replace(number,"");
console.log(text); //AA
console.log(number); //112
const incremented = parseInt(number) + 1;
console.log(incremented);
Using LOCATE, IF,LEAST and SUBSTRING over two sub-query can achieve the output result you're looking for.
SELECT VAL,
SUBSTRING(VAL,1,FIRSTNUM-1),
SUBSTRING(VAL,FIRSTNUM,999)+1
FROM
(SELECT VAL,LEAST(V0+0,V1+0,V2+0,V3+0,V4+0,V5+0,V6+0,V7+0,V8+0,V9+0) FIRSTNUM FROM
(SELECT VAL,
IF(LOCATE(0,VAL)=0,999,LOCATE(0,VAL)) V0,
IF(LOCATE(1,VAL)=0,999,LOCATE(1,VAL)) V1,
IF(LOCATE(2,VAL)=0,999,LOCATE(2,VAL)) V2,
IF(LOCATE(3,VAL)=0,999,LOCATE(3,VAL)) V3,
IF(LOCATE(4,VAL)=0,999,LOCATE(4,VAL)) V4,
IF(LOCATE(5,VAL)=0,999,LOCATE(5,VAL)) V5,
IF(LOCATE(6,VAL)=0,999,LOCATE(6,VAL)) V6,
IF(LOCATE(7,VAL)=0,999,LOCATE(7,VAL)) V7,
IF(LOCATE(8,VAL)=0,999,LOCATE(8,VAL)) V8,
IF(LOCATE(9,VAL)=0,999,LOCATE(9,VAL)) V9 FROM mytable) A ) B;
Here I use LOCATE to find the location of the number occurrence in the value then REPLACE to change the value to 999 if it returns 0. This is essential for the next operation using LEAST because if I leave it 0, it'll return all 0 instead. The reason I use LEAST is because if you look at the 4th data example in the fiddle it's AAAAA321. This will return the result in grid like the following:
+----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| VAL | V0 | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 |
+----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| AAA123 | 999 | 4 | 5 | 6 | 999 | 999 | 999 | 999 | 999 | 999 |
| AA4 | 999 | 999 | 999 | 999 | 3 | 999 | 999 | 999 | 999 | 999 |
| BBBB8 | 999 | 999 | 999 | 999 | 999 | 999 | 999 | 999 | 5 | 999 |
| AAAAA321 | 999 | 8 | 7 | 6 | 999 | 999 | 999 | 999 | 999 | 999 | <---this
| AAA45 | 999 | 999 | 999 | 999 | 4 | 5 | 999 | 999 | 999 | 999 |
+----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
The first number occurrence is actually '3' but because I construct the query running from 0-9, I'll always get the first number in front (in this case '1' is the 8th occurrence) despite it being on the middle or last position. That's why LEAST will correctly take which number is actually located first using LOCATE function.
In the last outer query, I use the result from the LEAST function (assigned as FIRSTNUM) as the defining value for the SUBSTRING. The first substring I use it as the end location subtract by 1 to get the strings and in the second substring I use it as the first location to get the number (I end the location with 999).
Fiddle: https://www.db-fiddle.com/f/F15cxiYJxGcozYUbQukeB/5
Edit: I realized I cannot use REPLACE because if the location is like 10, it will replace 0 to 999 which makes it become 1999 instead. So I use IF.
What does the +d in
function addMonths(d, n, keepTime) {
if (+d) {
mean?
The + operator returns the numeric representation of the object. So in your particular case, it would appear to be predicating the if on whether or not d is a non-zero number.
Reference here. And, as pointed out in comments, here.
Operator + is a unary operator which converts the value to a number. Below is a table with corresponding results of using this operator for different values.
+----------------------------+-----------+
| Value | + (Value) |
+----------------------------+-----------+
| 1 | 1 |
| '-1' | -1 |
| '3.14' | 3.14 |
| '3' | 3 |
| '0xAA' | 170 |
| true | 1 |
| false | 0 |
| null | 0 |
| 'Infinity' | Infinity |
| 'infinity' | NaN |
| '10a' | NaN |
| undefined | NaN |
| ['Apple'] | NaN |
| function(val){ return val }| NaN |
+----------------------------+-----------+
Operator + returns a value for objects which have implemented method valueOf.
let something = {
valueOf: function () {
return 25;
}
};
console.log(+something);
It is a unary "+" operator which yields a numeric expression. It would be the same as d*1, I believe.
As explained in other answers it converts the variable to a number. Specially useful when d can be either a number or a string that evaluates to a number.
Example (using the addMonths function in the question):
addMonths(34,1,true);
addMonths("34",1,true);
then the +d will evaluate to a number in all cases. Thus avoiding the need to check for the type and take different code paths depending on whether d is a number, a function or a string that can be converted to a number.