Return Last 4 Digits of Phone Number in Velocity - email

I need to return the last 4 digits of a Phone Number field (where the format isn't consistent) to display as a PIN.
Apologies for my grotesque attempt but what can I change below to display $PIN as the last 4 digits of the phone field?
#set ($PIN = ${lead.IR_Main_Phone__c}.substring(0,-4))

You should filter non-digit characters in lead.IR_Main_Phone__c var, then get last 4 digits.
Example:
String phoneno = "+1-(800)-555-2468";
$phoneno.replaceAll("\D", ""); //Removes non-digit characters
$PIN = $phoneno.substring(0,-4) //gives: 2468
Also, another way without substring:
String phoneno = "+1-(800)-555-2468";
$phoneno.replaceAll("\D", ""); //Removes non-digit characters
$phoneno.replaceAll("(?=\d{5})\d", ""); //removes all but last 4 digits
$PIN = $phoneno //gives: 2468

isn't velocity an animation library?
Just use regular javascript
var str = "123-4 5 6 7";
var numbersOnly = str.match(/\d+/g, str).join('');
console.log(numbersOnly.length); // outputs 7
console.log(numbersOnly.substr(numbersOnly.length-4)); //output "4567"
Edit: now uses regex to filter out non-numbers

Related

Number validation and formatting

I want to format, in real time, the number entered into a UITextField. Depending on the field, the number may be an integer or a double, may be positive or negative.
Integers are easy (see below).
Doubles should be displayed exactly as the user enters with three possible exceptions:
If the user begins with a decimal separator, or a negative sign followed by a decimal separator, insert a leading zero:
"." becomes "0."
"-." becomes "-0."
Remove any "excess" leading zeros if the user deletes a decimal point:
If the number is "0.00023" and the decimal point is deleted, the number should become "23".
Do not allow a leading zero if the next character is not a decimal separator:
"03" becomes "3".
Long story short, one and only one leading zero, no trailing zeros.
It seemed like the easiest idea was to convert the (already validated) string to a number then use format specifiers. I've scoured:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html
and
http://www.cplusplus.com/reference/cstdio/printf/
and others but can't figure out how to format a double so that it does not add a decimal when there are no digits after it, or any trailing zeros. For example:
x = 23.0
print (String(format: "%f", x))
//output is 23.000000
//I want 23
x = 23.45
print (String(format: "%f", x))
//output is 23.450000
//I want 23.45
On How to create a string with format?, I found this gem:
var str = "\(INT_VALUE) , \(FLOAT_VALUE) , \(DOUBLE_VALUE), \(STRING_VALUE)"
print(str)
It works perfectly for integers (why I said integers are easy above), but for doubles it appends a ".0" onto the first character the user enters. (It does work perfectly in Playground, but not my program (why???).
Will I have to resort to counting the number of digits before and after the decimal separator and inserting them into a format specifier? (And if so, how do I count those? I know how to create the format specifier.) Or is there a really simple way or a quick fix to use that one-liner above?
Thanks!
Turned out to be simple without using NumberFormatter (which I'm not so sure would really have accomplished what I want without a LOT more work).
let decimalSeparator = NSLocale.current.decimalSeparator! as String
var tempStr: String = textField.text
var i: Int = tempStr.count
//remove leading zeros for positive numbers (integer or real)
if i > 1 {
while (tempStr[0] == "0" && tempStr[1] != decimalSeparator[0] ) {
tempStr.remove(at: tempStr.startIndex)
i = i - 1
if i < 2 {
break
}
}
}
//remove leading zeros for negative numbers (integer or real)
if i > 2 {
while (tempStr[0] == "-" && tempStr[1] == "0") && tempStr[2] != decimalSeparator[0] {
tempStr.remove(at: tempStr.index(tempStr.startIndex, offsetBy: 1))
i = i - 1
if i < 3 {
break
}
}
}
Using the following extension to subscript the string:
extension String {
subscript (i: Int) -> Character {
return self[index(startIndex, offsetBy: i)]
}
}

How to get the number of real words in a text in Swift [duplicate]

This question already has answers here:
Number of words in a Swift String for word count calculation
(7 answers)
Closed 5 years ago.
Edit: there is already a question similar to this one but it's for numbers separated by a specific character (Get no. Of words in swift for average calculator). Instead this question is about to get the number of real words in a text, separated in various ways: a line break, some line breaks, a space, more than a space etc.
I would like to get the number of words in a string with Swift 3.
I'm using this code but I get imprecise result because the number is get counting the spaces and new lines instead of the effective number of words.
let str = "Architects and city planners,are \ndesigning buildings to create a better quality of life in our urban areas."
// 18 words, 21 spaces, 2 lines
let components = str.components(separatedBy: .whitespacesAndNewlines)
let a = components.count
print(a)
// 23 instead of 18
Consecutive spaces and newlines aren't coalesced into one generic whitespace region, so you're simply getting a bunch of empty "words" between successive whitespace characters. Get rid of this by filtering out empty strings:
let components = str.components(separatedBy: .whitespacesAndNewlines)
let words = components.filter { !$0.isEmpty }
print(words.count) // 17
The above will print 17 because you haven't included , as a separation character, so the string "planners,are" is treated as one word.
You can break that string up as well by adding punctuation characters to the set of separators like so:
let chararacterSet = CharacterSet.whitespacesAndNewlines.union(.punctuationCharacters)
let components = str.components(separatedBy: chararacterSet)
let words = components.filter { !$0.isEmpty }
print(words.count) // 18
Now you'll see a count of 18 like you expect.

Expected '33990Times Jobs' to be greater than 0

My code:
var listItemText = element.all(by.css(".list-group-item.ng-binding.ngscope")).get(0).getText()
.then(function(text){ return text.replace(/[\r\n]/g, "")
})
expect(listItemText).toBeGreaterThan(0);
How to compare if string is number with texts should be greater than 0 in protractor.
If you want to convert String to a Number you can either use parseFlaot for floating point numbers or parseInt for integers. As long as it will not start with letter characters it will cut off the non number part. Also watch out with parsing the number as it will also cut of leading 0s in front of a number - you might want to improve your regexp to grab only the number from where you expect it to be in the string to make it more bulletproof.
Also you don't need to use element.all(locator).get(0), element(locator) for multiple occurrences will always return first element found.
element(by.css(".list-group-item.ng-binding.ngscope")).getText()
.then(function(text){
var listItemText = text.replace(/[\r\n]/g, "");
expect(praseFloat(listItemText)).toBeGreaterThan(0);
});
Expected '33990Times Jobs' to be greater than 0
First of all, you are comparing a string with a number. And, the string itself contains the extra Times Jobs part. Let's extract all the digits from the text and use parseInt to convert a string to an integer:
var listItemText = element.all(by.css(".list-group-item.ng-binding.ngscope")).first().getText().then(function(text) {
return parseInt(text.match(/\d+/)[0]);
});
expect(listItemText).toBeGreaterThan(0);

Putting check digit in to form ISBN 10

I'm doing a barcode scanner and doing an in-app conversion of ISBN13 to ISBN10. I could now calculate out the check digit for the ISBN 10 but i do not know how to join it back to a 10 digit number.
What i did was to take out the prefixed "978" for the barcode 9780340961391 which then leaves it with 0340961391 and i only take out the 9 digits, leaving out the check digit of 1 for the isbn 13 which is then left with 034096139.
Then i calculate the check digit of isbn10 which is 2. The problem now is how do i add it to 034096139 to form the final ISBN10 of 0340961392? Thanks :)
I am assuming that your ISBN13 is a string and when adding the check digit back to the SBN number, you would not want to affect the 9 digit number. I would suggest:
/* SBNString = 034096139 */
NSString *ISBN10 = [NSString stringWithFormat:#"%#%u", SBNString, checkDigit];

Encoding a date into an ASCII barcode

I am investigating encoding of date information into a linear barcode that must be as short as possible. One idea we have had is encoding date information rather than using the ASCII characters for the date numerals.
The earliest date to be encoded is 01-JAN-2009
Date must be encoded using printable ASCII characters
If only the date matters (not the time):
Take the date to be encoded.
Subtract 1-1-2009 from it
Get the amount of elapsed days.
To encode this number as a printable sequence of ascii chars(ascii 48-127) do the following
pseudo code:
const int ASCIILOWRANGE = 48
const int ASCIIHIGHRANGE = 126
const char ASCIIENDMARKER = 127;
String convertToAscii(int numberOfDays)
{
String output = "";
while(numberOfDays>0)
{
output += (char) ASCIILOWRANGE + numberOfDays % (ASCIIHIGHRANGE-ASCIILOWRANGE);
numberOfDays /= (ASCIIHIGHRANGE-ASCIILOWRANGE);
}
output += ASCIIENDMARKER ;
return output;
}
//decoder
int convertToDays(String ascii)
{
char rightmost;
int numberOfDays = 0;
while(ascii.length>0)
{
rightmost = ascii[0];
if(rightmost == ASCIIENDMARKER ) break; //ready
numberOfDays *= (rightmost - ASCIILOWRANGE) * (ASCIIHIGHRANGE-ASCIILOWRANGE);
ascii = ascii.substr(1); //remove rightmost char from string
}
return numberOfDays ;
}
this way of encoding is the most dense. Since it encodes upto 96 days into the future in just 2 chars. 9216 days, in 3 chars, 884736 days in 4 chars.
Use the date itself: 01/01/2009 is a perfectly acceptable barcode under the Code39 style barcode.
If you don't mind a bit of processing logic during read, then you can do things like remove the "/" or whatever separator character you use.
Basically you would encode something like, "01012009" into the barcode, and then have the decode process just read the first two numbers as the month, the next two as the day, and the last 4 as the year. Since they're straight ascii it will work without any really hard processing.
A second alternative is to have 01-Jan-2009 as your "0" date, and then just encode the number of days since then. At which the decoding process would be to read the number, and then add that many days to 1/1/09. This would work that, Jan/5/2009 would be encoded as a "4" then when you wanted to read the date back out, you'd add 4 to Jan/1/09 to get Jan/5/09.