Reversing the order of a string value - swift

I have the following function which reverses a string value's display order.
I'm new to Swift and I'm trying to understand it's logic. What is going on with the '!pleh' value that it turns into 'Help!' ?
Thanks
func reverse(_ s: String) -> String {
var str = ""
for character in s.characters {
str = "\(character)" + str
}
return str
}
print (reverse("!pleH"))

In swift 4.0, directly call reversed on a string will get the job done
let str = "abc"
String(str.reversed()) // This will give you cba

Commented inline,
func reverse(_ s: String) -> String {
var str = ""
//.characters gives the character view of the string passed. You can think of it as array of characters.
for character in s.characters {
str = "\(character)" + str
//This will help you understand the logic.
//!+""
//p+!
//l+p! ... goes this way
print ( str)
}
return str
}
print (reverse("!pleH"))

Note: If you don't want to use the reversed() in-built function, then you can use the following code.
One-liner using Higher-order function "Reduce" on the string.
extension String {
func reverse() -> String { return self.reduce("") { "\($1)" + $0 } }
}

The function reversed(_:) iterates over each Character in the supplied string s, and simply concenates them in the reverse order.
// 1st pass in the 'for' loop:
// # start of iteration: 'str' equals ""
// update value of 'str' according to
// str = aCharacterAsString + str = "!" + ""
// 2nd pass in the 'for' loop:
// # start of iteration: str equals "!"
// update value of 'str' according to
// str = anotherCharacterAsString + str = "p" + "!"
// 3rd pass in the 'for' loop:
// # start of iteration: str equals "p!"
// update value of 'str' according to
// str = yetAnotherCharacterAsString + str = "l" + "p!"
// and so on ...
// after end of 'for' loop: str == "help!"
// this value of 'str' is then return to callee (which prints it)
A much simpler approach would be using reversed() on the CharacterView of the String instance:
let str = "!pleH"
print(String(str.characters.reversed())) // Help!
Swift 4 You can use it directly in your string
let str = "!pleH"
print(String(str.reversed())) // Help!

var string = "My,playground and my Swift"
var reverseString = ""
for str in string {
reverseString.insert(str, at: reverseString.startIndex)
}
print(reverseString)

In Swift 4 - To reverse string ::
func reverse(string:String) -> String {
var reverse = ""
for char in string {
reverse = char.description + reverse
}
return reverse
}
Input :: reverse(string: "Ashish Chhabra")
Output :: arbahhC hsihsA

var strnew = "hello world new"
var reverseStr = ""
for each in strnew
{
reverseStr = String(each) + reverseStr
}
print(reverseStr)

Different variation of answer using Character and Index.
//Reverse String
func reverse(str:String)->String{
var chars = [Character]()
for i in (0...str.count).reversed() {
let index = str.index(str.startIndex, offsetBy: i)
chars.append(str[index])
}
return String(chars)
}

You can use below code-
let str = "My name is Kplin Cours"
var reverseString = ""
for i in 0..<str.count {
let index = str.index(str.startIndex, offsetBy: (str.count - 1) - i)
// print(String(str[index]))
reverseString = reverseString + String(str[index])
}
print(reverseString) //sruoC nilpK si eman yM

let string = readLine()!
var resultString = ""
for i in 1...string.count {
let index = string.index(string.endIndex, offsetBy: -i)
resultString.append(string[index])
}
print(resultString)

let inputstr = "ABCDEFGHIGKLMNPO"
var resultstr = "";
for strchar in inputstr {
resultstr = String(strchar) + resultstr
}
print("Result = ",resultstr)

Swift 5
extension String {
func invertedEntropy() -> String {
var word = [Character]()
for char in self {
word.insert(char, at: 0)
}
return String(word)
}
}
var palindrome = "TENET"
palindrome.invertedEntropy()
// "TENET"

Simple as that!
let str = "Hello, world!"
let reversed = String(str.reversed())
print(reversed)

Related

Shuffle characters in a string in Swift

Can the new Swift 5 shuffle() method be used (directly, or in a more complicated incantation) to randomly shuffle the characters in a Swift string variable? (of length greater than 1)
You can simply try this nifty code
extension String {
func shuffleString(minLength : Int) -> String{
return self.count > minLength ? String(self.shuffled()) : self
}
}
var string = "Whatever is your string"
print(string.shuffleString(minLength: 1))
You can maybe try something like this.
var str = "Hello"
var shuffledString = String(str.shuffled())
try this function
func shuffleString(word: String) -> String {
var chars = Array(word.characters)
var result = ""
while chars.count > 0 {
let index = Int(arc4random_uniform(UInt32(chars.count - 1)))
chars[index].writeTo(&result)
chars.removeAtIndex(index)
}
return result
}
Try this one
var str = "Shuffle me please"
var shuffledStr: [Character]
if !str.isEmpty {
shuffledStr = str.shuffled()
print(String(shuffledStr))
}

In Swift How do I iterate over an array getting 2 variables when each pair of elements is a String? and a String

I want to iterate over an array String?, String repeated pair but I cannot form the "for case let (a,b) in array" correctly.
The best I have come up with is to create a temp struct of {String?, String} and create an array of the temp structs and then iterate it but I would like to skip this step.
Below is the basic example with the last for loop showing the error Xcode reports.
class Foo {
var s1: String?
var s2: String?
var s3: String?
}
let foo = Foo()
foo.s1="Test1"
foo.s2=nil
foo.s3="Test3"
let fooArray = [foo.s1, ", ", foo.s2, "; ", foo.s3,"."]
let fooArray1 = [foo.s1,foo.s2, foo.s3]
var text:String = ""
for case let prop? in fooArray1 {
text = text + prop + " / "
}
print(text)
// The above works but now I want to use a different separator
//base on the property name
text=""
for case let (prop, sep) in fooArray { // Error <= Expression Type
// [String?] is ambiguous without more context
text = text + prop + sep
}
print(text)
Here is what I have come up with
struct temp {
var prop:String?
var sep:String
init(_ prop:String?, _ sep:String) {
self.prop=prop
self.sep=sep
}
let ary:[temp] = [ temp(foo.s1,", "), temp(foo.s2,"; "), temp(foo.s3,".") ]
text = ""
for a in ary {
if let p = a.prop {
text = text + p + a.sep
}
}
print (text)
is there another way just using the for loop
for (a,b) in fooArray {
...
}
As noted by #RJE, the inferred type of fooArray, as defined in your code, is [String?].
Here is one way to make it work:
class Foo {
var s1: String?
var s2: String?
var s3: String?
}
let foo = Foo()
foo.s1 = "Test1"
foo.s2 = nil
foo.s3 = "Test3"
let fooArray1 = [foo.s1, foo.s2, foo.s3]
let separators = [", ", "; ", "."]
var text = ""
for i in fooArray1.indices {
if let p = fooArray1[i] {
text = text + p + separators[i]
}
}
print (text) //Test1, Test3.
Or
let zipped = zip(fooArray1, separators)
let text = zipped.map { tuple -> String in
if case let (x?, y) = tuple {
return x + y
} else {
return ""
}
}.joined()
print (text) //Test1,Test3.
Or
let fooArray = [foo.s1, ", ", foo.s2, "; ", foo.s3, "."]
var text = ""
var step = 1
var index = 0
while index < fooArray.count {
if let str = fooArray[index] {
step = 1
text += str
} else {
step = 2
}
index += step
}
print(text) //Test1, Test3.
It would be better to define the initializer this way :
class Foo {
var s1: String?
var s2: String?
var s3: String?
init(s1: String?, s2: String?, s3: String?) {
self.s1 = s1
self.s2 = s2
self.s3 = s3
}
}
let foo = Foo(s1: "Test1", s2: nil, s3: "Test3")
P.S: The desired output seems to be more appropriate for a description property of the Foo class.
Thanks for the answer I was hoping through this question to get a better understanding of how to use [for] parameters. But the while solution is the solution I would probably use with the following modifications
text = ""
var index = 0
while index < fooArray.count {
if let prop = fooArray[index] {
index += 1
let sep = fooArray[index]!
index += 1
text = text + prop + sep
} else {
index += 2
}
}

Swift. How to delete the character at the beginning and end of the string?

It is necessary to remove the quotes at the beginning and end of the line, if they are in the line
Could it be more beautiful?
var str = "\"Hello, playground\""
let quotes = "\""
if str.hasPrefix(quotes) && str.hasSuffix(quotes) {
let v = str.dropFirst()
str = String(v.dropLast())
}
print(str)
If you like a one liner:
let str = "\"\"\"Hello, playground\"\""
let unquoted = String(str.drop(while: { $0 == "\""}).reversed().drop(while: { $0 == "\""}).reversed())
print(unquoted) //Hello, playground
You could define these extensions to make it look a tad prettier:
extension String {
private func removeQuotesAndReverse() -> String {
return String(self.drop(while: { $0 == "\""}).reversed())
}
func unquote() -> String {
return self.removeQuotesAndReverse().removeQuotesAndReverse()
}
}
And use it like so:
let unquoted = "\"\"\"Hello, playground\"\"".unquote()
If you only need to remove the first and last quotes, if they are both present, then I would only add a check that the count is at least 2 characters, since a string like "\"" has quotes in both the prefix and suffix, but it's not between quotes:
extension String {
func withoutDoubleQuotes() -> String {
if self.hasPrefix("\""), self.hasSuffix("\""), self.count > 1 {
return String(self.dropFirst().dropLast())
}
return self
}
}
and use it like so:
"\"Hello, playground\"".withoutDoubleQuotes() //Hello, playground
"\"\"\"Hello, playground\"\"".withoutDoubleQuotes() //""Hello, playground"
"\"".withoutDoubleQuotes() //"
"\"\"".withoutDoubleQuotes() //
You can use Collection removeFirst and removeLast mutating methods:
var str = "\"Hello, playground\""
let quotes = "\""
if str.hasPrefix(quotes) && str.hasSuffix(quotes) && str != quotes {
str.removeFirst()
str.removeLast()
}
print(str) // "Hello, playground\n"
you can do so:
let str = "\"Hello, playground\""
let new = str.filter{$0 != "\""}

string replace substring without NSString API

I would like to be able to find and replace occurrences of a substring in a native Swift string without bridging to the NS class. How can I accomplish this?
This is not a duplicate of this question, as that question is about replacing a single character. This question is about finding and replacing a substring, which may contain many characters.
Method without Foundation:
extension String {
func replacing(_ oldString: String, with newString: String) -> String {
guard !oldString.isEmpty, !newString.isEmpty else { return self }
let charArray = Array(self.characters)
let oldCharArray = Array(oldString.characters)
let newCharArray = Array(newString.characters)
var matchedChars = 0
var resultCharArray = [Character]()
for char in charArray {
if char == oldCharArray[matchedChars] {
matchedChars += 1
if matchedChars == oldCharArray.count {
resultCharArray.append(contentsOf: newCharArray)
matchedChars = 0
}
} else {
for i in 0 ..< matchedChars {
resultCharArray.append(oldCharArray[i])
}
if char == oldCharArray[0] {
matchedChars = 1
} else {
matchedChars = 0
resultCharArray.append(char)
}
}
}
return String(resultCharArray)
}
}
Example usage:
let myString = "Hello World HelHelloello Hello HellHellooo"
print(myString.replacing("Hello", with: "Hi"))
Output:
Hi World HelHiello Hi HellHioo
Method using Foundation:
You can use the replacingOccurrences method on the String struct.
let myString = "Hello World"
let newString = myString.replacingOccurrences(of: "World", with: "Everyone")
print(newString) // prints "Hello Everyone"
generic and pure Swift approach
func splitBy<T: RangeReplaceableCollection>(_ s:T, by:T)->[T] where T.Iterator.Element:Equatable {
var tmp = T()
var res = [T]()
var i:T.IndexDistance = 0
let count = by.count
var pc:T.Iterator.Element {
get {
i %= count
let idx = by.index(by.startIndex, offsetBy: i)
return by[idx]
}
}
for sc in s {
if sc != pc {
i = 0
if sc != pc {
} else {
i = i.advanced(by: 1)
}
} else {
i = i.advanced(by: 1)
}
tmp.append(sc)
if i == count {
tmp.removeSubrange(tmp.index(tmp.endIndex, offsetBy: -i)..<tmp.endIndex)
res.append(tmp)
tmp.removeAll()
}
}
res.append(tmp)
return res
}
func split(_ s:String, by:String)->[String] {
return splitBy(s.characters, by: by.characters).map(String.init)
}
extension RangeReplaceableCollection where Self.Iterator.Element: Equatable {
func split(by : Self)->[Self] {
return splitBy(self, by: by)
}
}
how to use it?
let str = "simple text where i would like to replace something with anything"
let pat = "something"
let rep = "anything"
let s0 = str.characters.split(by: pat.characters).map(String.init)
let res = s0.joined(separator: rep)
print(res) // simple text where i would like to replace anything with anything
let res2 = split(str, by: pat).joined(separator: rep)
print(res2) // simple text where i would like to replace anything with anything
let arr = [1,2,3,4,1,2,3,4,1,2,3]
let p = [4,1]
print(arr.split(by: p)) // [[1, 2, 3], [2, 3], [2, 3]]

Reverse Strings without using predefined functions

Pardon me as I am a newbie on this language.
Edit: Is there a way to reverse the position of a array element?
I am trying to create a function that test the given input if its a palindrome or not. I'm trying to avoid using functions using reversed()
let word = ["T","E","S","T"]
var temp = [String]()
let index_count = 3
for words in word{
var text:String = words
print(text)
temp.insert(text, atIndex:index_count)
index_count = index_count - 1
}
Your approach can be used to reverse an array. But you have to
insert each element of the original array at the start position
of the destination array (moving the other elements to the end):
// Swift 2.2:
let word = ["T", "E", "S", "T"]
var reversed = [String]()
for char in word {
reversed.insert(char, atIndex: 0)
}
print(reversed) // ["T", "S", "E", "T"]
// Swift 3:
let word = ["T", "E", "S", "T"]
var reversed = [String]()
for char in word {
reversed.insert(char, at: 0)
}
print(reversed) // ["T", "S", "E", "T"]
The same can be done on the characters of a string directly:
// Swift 2.2:
let word = "TEST"
var reversed = ""
for char in word.characters {
reversed.insert(char, atIndex: reversed.startIndex)
}
print(reversed) // "TSET"
// Swift 3:
let word = "TEST"
var reversed = ""
for char in word.characters {
reversed.insert(char, at: reversed.startIndex)
}
print(reversed)
Swift 5
extension String {
func invert() -> String {
var word = [Character]()
for char in self {
word.insert(char, at: 0)
}
return String(word)
}
}
var anadrome = "god"
anadrome.invert()
// "dog"
Here's my solution:
extension String {
func customReverse() -> String {
var chars = Array(self)
let count = chars.count
for i in 0 ..< count/2 {
chars.swapAt(i, count - 1 - i)
}
return String(chars)
}
}
let input = "abcdef"
let output = input.customReverse()
print(output)
You can try it here.
func reverse(_ str: String) -> String {
let arr = Array(str) // turn the string into an array of all of the letters
let reversed = ""
for char in arr {
reversed.insert(char, at: reversed.startIndex)
}
return reversed
}
To use it:
let word = "hola"
let wordReversed = reverse(word)
print(wordReversed) // prints aloh
Another solution for reversing:
var original : String = "Test"
var reversed : String = ""
var c = original.characters
for _ in 0..<c.count{
reversed.append(c.popLast()!)
}
It simply appends each element of the old string that is popped, starting at the last element and working towards the first
Solution 1
let word = "aabbaa"
let chars = word.characters
let half = chars.count / 2
let leftSide = Array(chars)[0..<half]
let rightSide = Array(chars.reverse())[0..<half]
let palindrome = leftSide == rightSide
Solution 2
var palindrome = true
let chars = Array(word.characters)
for i in 0 ..< (chars.count / 2) {
if chars[i] != chars[chars.count - 1 - i] {
palindrome = false
break
}
}
print(palindrome)
static func reverseString(str : String) {
var data = Array(str)
var i = 0// initial
var j = data.count // final
//either j or i for while , data.count/2 buz only half we need check
while j != data.count/2 {
print("befor i:\(i) j:\(j)" )
j = j-1
data.swapAt(i, j) // swapAt API avalible only for array in swift
i = i+1
}
print(String(data))
}
//Reverse String
let str = "Hello World"
var reverseStr = ""
for char in Array(str) {
print(char)
reverseStr.insert(char, at: str.startIndex)
}
print(reverseStr)