Last Instance of Character - string

I'm looking to find the last instance of a character in a string. Given the different way Swift deals with strings (ranges), I was hoping someone has run into this before as I can't seem to figure out the best way to deal with it.
The string I'd like to parse is similar to "http://imanimage_thatlooks_likethis_andmypixare_380.jpg". I need to parse the segment between the last "_" and the last ".". So the number 380. Each link is formatted this way, but the substring methodology for Swift is still a bit foreign to me, with the inclusion of different byte lengths.
Thanks in advance!

// regular expression to find substring between last "_" and last "."
let sourceStr = "abc_defg_hijk_lmn.xyz"
let regex = NSRegularExpression( pattern: "_([^_]*)\\.[^\\.]*$", options:nil, error:nil );
if let matchingResult = regex?.firstMatchInString( sourceStr, options: nil, range: NSMakeRange( 0, countElements( sourceStr ) ) ) {
let matchingRange = matchingResult.rangeAtIndex(1)
let matchingString = (sourceStr as NSString).substringWithRange( matchingRange )
}

Related

Need to extract the last word in a Rust string

I am doing some processing of a string in Rust, and I need to be able to extract the last set of characters from that string. In other words, given a string like the following:
some|not|necessarily|long|name
I need to be able to get the last part of that string, namely "name" and put it into another String or a &str, in a manner like:
let last = call_some_function("some|not|necessarily|long|name");
so that last becomes equal to "name".
Is there a way to do this? Is there a string function that will allow this to be done easily? If not (after looking at the documentation, I doubt that there is), how would one do this in Rust?
While the answer from #effect is correct, it is not the most idiomatic nor the most performant way to do it. It'll walk the entire string and match all of the |s to reach the last. You can make it better, but there is a method of str that does exactly what you want - rsplit_once():
let (_, name) = s.rsplit_once('|').unwrap();
// Or
// let name = s.rsplit_once('|').unwrap().1;
//
// You can also use a multichar separator:
// let (_, name) = s.rsplit_once("|").unwrap();
// But in the case of a single character, a `char` type is likely to be more performant.
Playground.
You can use the String::split() method, which will return an iterator over the substrings split by that separator, and then use the Iterator::last() method to return the last element in the iterator, like so:
let s = String::from("some|not|necessarily|long|name");
let last = s.split('|').last().unwrap();
assert_eq!(last, "name");
Please also note that string slices (&str) also implement the split method, so you don't need to use std::String.
let s = "some|not|necessarily|long|name";
let last = s.split('|').last().unwrap();
assert_eq!(last, "name");

Swift string strip all characters but numbers and decimal point?

I have this string:
Some text: $ 12.3 9
I want to get as a result:
12.39
I have found examples on how to keep only numbers, but here I am wanting to keep the decimal point "."
What's a good way to do this in Swift?
This should work (it's a general approach to filtering on a set of characters) :
[EDIT] simplified and adjusted to Swift3
[EDIT] adjusted to Swift4
let text = "$ 123 . 34 .876"
let decimals = Set("0123456789.")
var filtered = String( text.filter{decimals.contains($0)} )
If you need to ignore anything past the second decimal point add this :
filtered = filtered.components(separatedBy:".") // separate on decimal point
.prefix(2) // only keep first two parts
.joined(separator:".") // put parts back together
Easiest and simplest reusable way: you can use this regex replacement option. This replaces all characters except 0 to 9 and dot (.) .
let yourString = "$123. 34"
//pattern says except digits and dot.
let pattern = "[^0-9.]"
do {
let regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions.CaseInsensitive)
//replace all not required characters with empty string ""
let string_With_Just_Numbers_You_Need = regex.stringByReplacingMatchesInString(yourString, options: NSMatchingOptions.WithTransparentBounds, range: NSMakeRange(0, yourString.characters.count), withTemplate: "")
//your number converted to Double
let convertedToDouble = Double(string_With_Just_Numbers_You_Need)
} catch {
print("Cant convert")
}
One possible solution to the question follows below. If you're working with text fields and currency, however, I suggest you take a look at the thread Leo Dabus linked to.
extension String {
func filterByString(myFilter: String) -> String {
return String(self.characters.filter {
myFilter.containsString(String($0))
})
}
}
var a = "$ 12.3 9"
let myFilter = "0123456789.$"
print(a.filterByString(myFilter)) // $12.39

AS3: Get all substrings from a string in a specified array

This is not a duplicate because all the other questions were not in AS3.
Here is my problem: I am trying to find some substrings that are in the "storage" string, that are in another string. I need to do this because my game server is sending the client random messages that contain on of the strings in the "storage" string. The strings sent from the server will always begin with: "AA_".
My code:
private var storage:String = AA_word1:AA_word2:AA_word3:AA_example1:AA_example2";
if(test.indexOf("AA_") >= 0) {
//i dont even know if this is right...
}
}
If there is a better way to do this, please let me know!
Why not just using String.split() :
var storage:String = 'AA_word1:AA_word2:AA_word3:AA_example1:AA_example2';
var a:Array = storage.split('AA_');
// gives : ,word1:,word2:,word3:,example1:,example2
// remove the 1st ","
a.shift();
trace(a); // gives : word1:,word2:,word3:,example1:,example2
Hope that can help.
Regular Expressions are the right tool for this job:
function splitStorage(storage: String){
var re: RegExp = /AA_([\w]+):?/gi;
// Execute the regexp until it
// stops returning results.
var strings = [];
var result: String;
while(result = re.exec(storage)){
strings.push(result[1]);
}
return strings;
}
The important part of this is the regular expression itself: /AA_([\w]+):?/gi
This says find a match starting with AA_, followed by one-or-more alphanumeric characters (which we capture) ([\w]+), optionally followed by a colon.
The match is then made global and case insensitive with /gi.
If you need to capture more than just letters and numbers - like this: "AA_word1 has spaces and [special-characters]:" - then add those characters to the character set inside the capture group.
e.g. ([-,.\[\]\s\w]+) will also match hyphen, comma, full-stop, square brackets, whitespace and alphanumeric characters.
Also you could do it with just one line, with a more advanced regular expression:
var storage:String = 'AA_word1:AA_word2:AA_word3:AA_example1:AA_example2';
const a:Array = storage.match(/(?<=AA_)\w+(?=:|$)/g);
so this means: one or more word char, preceeded by "AA_" and followed by ":" or the end of string. (note that "AA_" and ":" won't be included into the resulting match)

Is there an equivalent to the string function String(format: ...) using Swift formatting

I'm starting to like the Swift string formatting since it uses variable names in the string rather than ambiguous formatting tags like "%#"
I want to load a large string from a file that has Swift-style formatting in it (like this)
Now is the time for all good \(who) to come to babble incoherently.
Then I want to feed the contents of that String variable into a statement that lest me replace
\(who)
with the contents of the constant/variable who at runtime.
The code below works with a string constant as the formatting string.
let who = "programmers"
let aString = "Now is the time for all good \(who) to come to babble incoherently."
That code does formatting of a quoted string that appears in-line in my code.
Instead I want something like the code
let formatString = "Now is the time for all good %# to come to babble incoherently."
aString = String(format: formatString, who)
But where I can pass in a Swift-style format string in a constant/variable I read from a file.
Is that possible? I didn't have any luck searching for it since I wasn't exactly sure what search terms to use.
I can always use C-style string formatting and the String class' initWithFormat method if I have to...
I don't think there's a way to do this. String interpolation is implemented via conforming to the StringInterpolationConvertible protocol, and presumably you're hoping to tap into that in the same way you can tap into the methods required by StringLiteralConvertible, a la:
let someString = toString(42)
// this is the method String implements to conform to StringLiteralConvertible
let anotherString = String(stringLiteral: someString)
// anotherString will be "42"
print(anotherString)
Unfortunately, you can't do quite the same trick with StringInterpolationConvertible. Seeing how the protocol works may help:
struct MyString: Printable {
let actualString: String
var description: String { return actualString }
}
extension MyString: StringInterpolationConvertible {
// first, this will get called for each "segment"
init<T>(stringInterpolationSegment expr: T) {
println("Processing segment: " + toString(expr))
actualString = toString(expr)
}
// here is a type-specific override for Int, that coverts
// small numbers into words:
init(stringInterpolationSegment expr: Int) {
if (0..<4).contains(expr) {
println("Embigening \(expr)")
let numbers = ["zeo","one","two","three"]
actualString = numbers[expr]
}
else {
println("Processing segment: " + toString(expr))
actualString = toString(expr)
}
}
// finally, this gets called with an array of all of the
// converted segments
init(stringInterpolation strings: MyString...) {
// strings will be a bunch of MyString objects
actualString = "".join(strings.map { $0.actualString })
}
}
let number = 3
let aString: MyString = "Then shalt thou count to \(number), no more, no less."
println(aString)
// prints "Then shalt thou count to three, no more, no less."
So, while you can call String.init(stringInterpolation:) and String.init(stringInterpolationSegment:) directly yourself if you want (just try String(stringInterpolationSegment: 3.141) and String(stringInterpolation: "blah", "blah")), this doesn't really help you much. What you really need is a facade function that coordinates the calls to them. And unless there's a handy pre-existing function in the standard library that does exactly that which I've missed, I think you're out of luck. I suspect it's built into the compiler.
You could maybe write your own to achieve your goal, but a lot of effort since you'd have to break up the string you want to interpolate manually into bits and handle it yourself, calling the segment init in a loop. Also you'll hit problems with calling the combining function, since you can't splat an array into a variadic function call.
I don't think so. The compiler needs to be able to resolve the interpolated variable at compile time.
I'm not a Swift programmer, specifically, but I think you can workaround it to something pretty close to what you want using a Dictionary and standard string-replacing and splitting methods:
var replacement = [String: String]()
replacement["who"] = "programmers"
Having that, you can try to find the occurrences of "\(", reading what is next and prior to a ")", (this post can help with the split part, this one, with the replacing part), finding it in the dictionary, and reconstructing your string from the pieces you get.
this one works like a charm:
let who = "programmers"
let formatString = "Now is the time for all good %# to come to babble incoherently."
let aString = String(format: formatString, who)

Lua Pattern Exclusion

I have a predefined code, e.g."12-345-6789", and wish to match the first and last portions with Lua patterns, e.g. "12-6789". An exclusion of the second number set and the hyphen should work but I am having trouble figuring that out with patterns or if it is possible.
I know I could capture each individually like so
code = "12-345-6789"
first, middle, last = string.match(code, "(%d+)-(%d+)-(%d+)")
and use that but it would require a lot of code rewriting on my part. I would ideally like to take the current table of pattern matches and add it to be used with string.match
lcPart = { "^(%d+)", "^(%d+%-%d+)", "(%d+)$", ?new pattern here? }
code = "12-345-6789"
newCode = string.match(code, lcPart[4])
You can't do this with one capture, but it's trivial to splice the results of two captures together:
local first, last = string.match(code, "(%d+)%-%d+%-(%d+)")
local newid = first .. "-" .. last
If you're trying to match against a list of patterns, it may be better to refactor it into a list of functions instead:
local matchers = {
function(s) return string.match(s, "^(%d+)") end,
function(s) return string.match(s, "^(%d+%-%d+)") end,
-- ...
function(s)
local first, last = string.match(code, "(%d+)%-%d+%-(%d+)")
return first .. "-" .. last
end,
}
for _,matcher in ipairs(matcher) do
local match = matcher(code)
if match then
-- do something
end
end
I know this is an old thread, but someone might still find this useful.
If you need only the first and last sets of digits, separated by a hyphen you could use string.gsub for that
local code = "12-345-6789"
local result = string.gsub(code, "(%d+)%-%d+%-(%d+)", "%1-%2")
This will simply return the string "12-6789" by using the first and second captures from the pattern.

Resources