I'm new to Swift Programming. I would like to ask if anyone can help me to return only alphanumeric substring from a string ?
Example:
Input = "wolf & lion"
Output = "wolflion"
I wonder if there is any solution besides regex.
Thank you
try this:
let outputStr = "wolf & lion".components(separatedBy: CharacterSet.alphanumerics.inverted)
.joined()
print(outputStr)//wolflion
var a = "abs1 2csd^!#awerqwe"
let b = a.characters.map { (char) -> String in
if let charRange = String(char).rangeOfCharacter(from: CharacterSet.alphanumerics) {
return String(char)
} else {
return ""
}
}.joined()
//OR use unicode scalar
let c = a.unicodeScalars.map { (char) -> String in
if CharacterSet.alphanumerics.contains(char) {
return String(char)
} else {
return ""
}
}.joined()
Output: abs12csdawerqwe
Please check :
let str = "wolf & lion"
let charset = str.trimmingCharacters(in: CharacterSet.alphanumerics)
let alphanumericString = str.components(separatedBy: charset).joined(separator: "")
print(alphanumericString) // wolflion
Related
Let's say I have this:
something,"another thing"
This can be split easily with a normal split function.
Now I want to have more complicated syntax and I do:
something,"in a string, oooh",rgba(4,2,0)
This does not work with a regular split function.
I tried using things like replacing commas inside of specific types of tokens, but that became too over-complicated and I feel there has to be a better way.
Then I tried with regular expressions, which worked, until I had to add a new feature, which wouldn't work with the regexp I had (which was pretty bad), also regexp matches can be slow, and this is supposed to be as fast as possible.
What would be a better way to solve this?
Here is the source repo for extra context https://github.com/hyprland-community/hyprparse
And the format in question is the hyprland config format
Iterate over the string keeping a context state:
None
Inside a "..."
Inside a (...)
Inside a context, comma has no separator meaning.
Limitations: This is a midnight hack!
See also Rust Playground
fn split(s: String) -> Vec<String> {
let mut context = None;
let mut i = 0;
let mut start = 0;
let mut items = Vec::new();
for c in s.chars() {
if context == Some('"') {
if c == '"' {
context = None;
}
i = i+1;
continue;
} else if context == Some('(') {
if c == ')' {
context = None;
}
i = i+1;
continue;
}
if c == '"' || c == '(' {
context = Some(c);
}
if c == ',' && context.is_none() {
items.push(s[start..i].to_string());
start = i + 1;
}
i = i+1;
}
items.push(s[start..i].to_string());
items
}
fn main() {
let s = "something,\"in a string, oooh\",rgba(4,2,0)".to_string();
println!("{:?}", split(s));
// -> ["something", "\"in a string, oooh\"", "rgba(4,2,0)"]
}
Thanks for all the help everyone, I eventually came up with my own solution with the help of people I knew IRL, here is my solution:
fn previous_rgb(index: usize, chars: Vec<char>) -> bool {
let string: String = chars[index-3..index].iter().collect();
let string = string.as_str();
if string == "gba" || string == "rgb" {
true
} else {
false
}
}
fn splitter<Str: ToString>(s: Str) -> Vec<String> {
let mut is_in_rgb = false;
let mut is_in_str = false;
let mut last = 0;
let chars: Vec<_> = s.to_string().chars().collect();
let mut final_str = vec![];
for (index, c) in chars.iter().enumerate() {
if *c == '(' && previous_rgb(index, chars.clone()) && !is_in_str {
is_in_rgb = true;
} else if *c == ')' && is_in_rgb && !is_in_str {
is_in_rgb = false;
} else if *c == '"' && is_in_str {
is_in_str = false;
} else if *c == '"' && !is_in_str {
is_in_str = true;
} else if *c == ',' && !is_in_str && !is_in_rgb {
final_str.push(chars[last..index].iter().collect());
last = index + 1
};
}
final_str.push(chars[last..].iter().collect());
final_str
}
fn main() {
let splitted = splitter(r#"test,test: rgba(5,4,3),"test2, seperated""#);
println!("{splitted:?}");
}
I'm currently using this String extension to Capitalize the letter of each word in a textField :
"happy sunshine" .toTitleCase() gives "Happy Sunshine"
extension StringExtension on String {
String toTitleCase() => replaceAll(RegExp(' +'), ' ')
.split(' ')
.map((str) => str.toCapitalized())
.join(' ');
String toCapitalized() =>
length > 0 ? '${this[0].toUpperCase()}${substring(1).toLowerCase()}' : '';
}
but I'd also like to Capitalize letters that come after a hyphen - with the same toTitleCase method
ex : "very-happy sunshine" .toTitleCase() would give "Very-Happy Sunshine"
Currently .toTitleCase() gives "Very-happy Sunshine" : (
I am sure a wizard with expert knowledge in regular expression can do this better but I think this solution solves your problem:
void main() {
print('happy sunshine'.toTitleCase()); // Happy Sunshine
print('very-happy sunshine'.toTitleCase()); // Very-Happy Sunshine
}
extension StringExtension on String {
String toTitleCase() => replaceAllMapped(
RegExp(r'(?<= |-|^).'), (match) => match[0]!.toUpperCase());
}
If you call the method a lot of times, you might consider having the RegExp as a cached value like:
extension StringExtension on String {
static final RegExp _toTitleCaseRegExp = RegExp(r'(?<= |-|^).');
String toTitleCase() =>
replaceAllMapped(_toTitleCaseRegExp, (match) => match[0]!.toUpperCase());
}
You can tweak your code as well. But I've used the same thing somewhere in my project so you can do something like this as well.
Working: First I'm creating an empty array looping through each character in a particular string and checking if space (" ") and hyphen ("-") are current_position - 1 then I'm making current_position to uppercase.
String capitalize(String s) {
String result = "";
for (int i = 0; i < s.length; i++) {
if (i == 0) {
result += s[i].toUpperCase();
} else if (s[i - 1] == " ") {
result += s[i].toUpperCase();
} else if (s[i - 1] == "-") {
result += s[i].toUpperCase();
} else {
result += s[i];
}
}
return result;
}
I'm trying to write a regular expression to remove white spaces from just the beginning of the word, not after, and only a single space after the word.
Used RegExp:
var re = new RegExp(/^([a-zA-Z0-9]+\s?)*$/);
Test Exapmle:
1) test[space]ing - Should be allowed
2) testing - Should be allowed
3) [space]testing - Should not be allowed
4) testing[space] - Should be allowed but have to trim it
5) testing[space][space] - should be allowed but have to trim it
Only one space should be allowed. Is it possible?
To match, what you need, you can use
var re = /^([a-zA-Z0-9]+\s)*[a-zA-Z0-9]+$/;
Maybe you could shorten that a bit, but it matches _ as well
var re = /^(\w+\s)*\w+$/;
function validate(s) {
if (/^(\w+\s?)*\s*$/.test(s)) {
return s.replace(/\s+$/, '');
}
return 'NOT ALLOWED';
}
validate('test ing') // => 'test ing'
validate('testing') // => 'testing'
validate(' testing') // => 'NOT ALLOWED'
validate('testing ') // => 'testing'
validate('testing ') // => 'testing'
validate('test ing ') // => 'test ing'
BTW, new RegExp(..) is redundant if you use regular expression literal.
This one does not allow preceding and following spaces plus only one space between words. Feel free to add any special characters You want.
^([A-Za-z]+ )+[A-Za-z]+$|^[A-Za-z]+$
demo here
Working code- Inside my name.addTextChangedListener():
public void onTextChanged(CharSequence s, int start, int before, int count) {
String n = name.getText().toString();
if (n.equals(""))
name.setError("Name required");
else if (!n.matches("[\\p{Alpha}\\s]*\\b") | n.matches(".*\\s{2}.*") | n.matches("\\s.*")) {
if (n.matches("\\s.*"))
name.setError("Name cannot begin with a space");
else if (n.matches(".*\\s{2}.*"))
name.setError("Multiple spaces between texts");
else if (n.matches(".*\\s"))
name.setError("Blank space at the end of text");
else
name.setError("Non-alphabetic character entered");
}
}
You could try adapting this to your code.
var f=function(t){return Math.pow(t.split(' ').length,2)/t.trim().split(' ').length==2}
f("a a")
true
f("a a ")
false
f("a a")
false
f(" a a")
false
f("a a a")
false
Here is a solution without regular expression.
Add this script inside document.ready function it will work.
var i=0;
jQuery("input,textarea").on('keypress',function(e){
//alert();
if(jQuery(this).val().length < 1){
if(e.which == 32){
//alert(e.which);
return false;
}
}
else {
if(e.which == 32){
if(i != 0){
return false;
}
i++;
}
else{
i=0;
}
}
});
const handleChangeText = text => {
let lastLetter = text[text.length - 1];
let secondLastLetter = text[text.length - 2];
if (lastLetter === ' ' && secondLastLetter === ' ') {
return;
}
setInputText(text.trim());
};
use this
^([A-Za-z]{5,}|[\s]{1}[A-Za-z]{1,})*$
Demo:-https://regex101.com/r/3HP7hl/2
I am making a converter to convert a string to binary and I want to change the color of every 8th character of the resulting binary conversion result to red to symbolize the beginning of each ascii character. The user enters a string a text input and the converted result is displayed in a text area like so:
Every 8th 0 or 1 should be red.
I'm not sure where to begin and is this even possible? And if I were to reverse the converter (user enters binary and its converted to ascii characters) could it still work? Thanks.
Edit:
I am adding "<font color='red'>" and "</font>" to the beginning and end of every eighth binary digit but the result displayed is literally "<font color='red'>0</font>", it is not applying the html styling.
My TextInput sets the TextArea.text whenever the user types using a C++ function.
TextInput {
...
onTextChanged: {
uiText.setBinaryString(myTextInput.text)
myTextAreaText.text = uiText.getBinaryString()
}
}
C++ functions
void UITextConnector::setBinaryString(QString s)
{
binaryString = convertToBinary(s);
}
QString UITextConnector::getBinaryString()
{
return binaryString;
}
QString UITextConnector::convertToBinary(QString qs)
{
std::string resultString;
if (binaryMode) {
std::string qStringConverted = qs.toStdString();
for (std::size_t i = 0; i < qStringConverted.size(); i++) {
std::bitset<8> b(qStringConverted.c_str()[i]);
std::string nextBinary = b.to_string();
nextBinary = "<font color='#00AA00'>" + nextBinary.substr(0,1) + "</font>" + nextBinary.substr(1);
resultString += nextBinary;
}
} else {
std::string qStringConverted = qs.toStdString();
for (std::size_t i = 0; i < qStringConverted.size() ; i = i + 8) {
resultString += UITextConnector::strToChar(qStringConverted.substr(i, i+8).c_str());
}
}
return QString::fromStdString(resultString);
}
However, this only works if I use a label but not when I use a textArea.
Since you didn't provide any source or whatever it is too difficult to understand what is your fail. Anyway, I would do that in the following way:
TextArea {
id: txt
anchors.fill: parent
anchors.margins: 10
textFormat: TextEdit.RichText
text: ""
function setText(str)
{
var arr = str.match(/.{1,8}/g) || [];
var result = "";
for(var index in arr)
{
result += "<font color='red'>" + arr[index].substring(0, 1) + "</font>" + arr[index].substring(1);
}
txt.text = result;
}
Component.onCompleted: {
txt.setText("aaaaaaaabbbbbbbbccccccccdddd");
}
}
http://play.golang.org/p/GM0SWo0qGs
This is my code and playground.
func insert_comma(input_num int) string {
temp_str := strconv.Itoa(input_num)
var validID = regexp.MustCompile(`\B(?=(\d{3})+$)`)
return validID.ReplaceAllString(temp_str, ",")
}
func main() {
fmt.Println(insert_comma(1000000000))
}
Basically, my desired input is 1,000,000,000.
And the regular expression works in Javascript but I do not know how to make this Perl regex work in Go. I would greatly appreciate it. Thanks,
Since lookahead assertion seems to be not supported, I'm providing you a different algorithm with no regexp:
Perl code:
sub insert_comma {
my $x=shift;
my $l=length($x);
for (my $i=$l%3==0?3:$l%3;$i<$l;$i+=3) {
substr($x,$i++,0)=',';
}
return $x;
}
print insert_comma(1000000000);
Go code: Disclaimer: I have zero experience with Go, so bear with me if I have errors and feel free to edit my post!
func insert_comma(input_num int) string {
temp_str := strconv.Itoa(input_num)
var result []string
i := len(temp_str)%3;
if i == 0 { i = 3 }
for index,element := range strings.Split(temp_str, "") {
if i == index {
result = append(result, ",");
i += 3;
}
result = append(result, element)
}
return strings.Join(result, "")
}
func main() {
fmt.Println(insert_comma(1000000000))
}
http://play.golang.org/p/7pvo7-3G-s