How to reverse the Linked List in Swift extension? - swift

I want to reverse the Single Linked List in extension, but finally it's failed.can someone help me? thanks.
public class List<T: Equatable> {
var value: T!
var nextItem: List<T>?
public convenience init!(_ values: T...) {
self.init(Array(values))
}
init!(var _ values: Array<T>) {
if values.count == 0 {
return nil
}
value = values.removeFirst()
nextItem = List(values)
}
}
// Reverse a linked list.
extension List {
func reverse() {
}
}

I have a solution here. Please read the comments, its all evident from the code too. Also I have added a 'description' via CustomStringConvertible to the list to help debugging and printing.
public class List<T: Equatable>{
var value: T!
var nextItem: List<T>?
public convenience init!(_ values: T...) {
self.init(Array(values))
}
init!(_ values: Array<T>) {
if values.count == 0 {
return nil
}
var valuesCopy = values
value = valuesCopy.removeFirst()
nextItem = List(Array(valuesCopy))
}
}
extension List : CustomStringConvertible{
public var description: String {
var desc = String()
var listRef : List<T>? = self
while listRef != nil {
desc += "\((listRef?.value)!) "
listRef = listRef?.nextItem
}
return desc
}
}
extension List{
func reverse() -> List?{
// Iterate through each item, and reverse its link until you visit the last node in the list.
// Once you reach the end, All items except the last one would have
// their links reversed.
var nextNode : List<T>? = self.nextItem
var prevNode : List<T>? = nil
var currentNode : List<T>? = self
while nextNode != nil{
currentNode?.nextItem = prevNode
prevNode = currentNode
currentNode = nextNode
nextNode = currentNode?.nextItem
}
//Ensure the last item in the list too has its links reversed.
currentNode?.nextItem = prevNode
return currentNode
}
}
var list = List(1,2,3,5)
print(list ?? "Failed to create the list")
if let reversed = list.reverse(){
print(reversed)
}

Related

protobuf based spring boot end point giving no output to swift client

I have a spring boot based micro-service endpoint which produces protobuf. Here is the .proto definition:
syntax = "proto3";
package TournamentFilterPackage;
import "google/protobuf/any.proto";
option java_package = "com.mycompany.service.tournament.proto";
option java_outer_classname = "TournamentCompleteData";
message TournamentData {
repeated TournamentRecord tournamentRecords = 1;
}
message TournamentRecord {
int64 id = 1;
Date start = 2;
float prize = 3;
string name = 4;
string speed = 5;
string type = 6;
float buyIn = 7;
int32 noOfParticipants = 8;
string status = 9;
}
message Date {
int32 year = 1;
int32 month = 2;
int32 day = 3;
}
message PokerResponseProto {
repeated int32 errorCodes = 1;
google.protobuf.Any responseObject = 2;
}
Here is my rest controller:
#ApiOperation(value="Complete Tournament Data", response = PokerResponseProto.class)
#GetMapping(value="/tournaments/completedata", produces = "application/x-protobuf")
public ResponseEntity<PokerResponseProto> getCompleteTournamentdata() {
if (logger.isInfoEnabled()) {
logger.info("BEGIN::/lobby/api/v1//tournaments/completedata/ " + "GET ::");
}
List<TournamentTypeResponseDto> tournamentTypeResponseDtos = new ArrayList<>();
List<TournamentRecord> tournamentRecords = new ArrayList<>();
ResponseEntity<PokerResponseProto> pokerResponse = null;
try {
tournamentTypeResponseDtos =
tournamentTypeDataService.getCompleteTournamentList();
for(TournamentTypeResponseDto t:tournamentTypeResponseDtos) {
tournamentRecords.add(controllerUtils.buildTournamentRecord(t));
}
TournamentData.Builder tournamentDataBuilder =
TournamentData.newBuilder().addAllTournamentRecords(tournamentRecords);
pokerResponse = new ResponseEntity<>(BKPokerResponseProto.newBuilder()
.setResponseObject(Any.pack(tournamentDataBuilder.build()))
.build(),
HttpStatus.OK);
logger.info("pokerResponse: {}", pokerResponse.toString());
} catch (PokerException pe) {
if (this.logger.isErrorEnabled()) {
this.logger.error(pe.getMessage(), bkpe);
}
List<Integer> errorCodeValue = controllerUtils
.convertErrorCodesToInt(bkpe.getErrorCodes());
pokerResponse = new ResponseEntity<>(PokerResponseProto.newBuilder()
.addAllErrorCodes(errorCodeValue)
.build(), HttpStatus.INTERNAL_SERVER_ERROR);
}
if (logger.isInfoEnabled()) {
logger.info("RETURN::/lobby/api/v1//tournaments/completedata/ " + "GET :: {}",
pokerResponse.toString());
}
return pokerResponse;
}
Here is the code snippet from ControllerUtils class:
public TournamentRecord buildTournamentRecord(TournamentTypeResponseDto dto) {
Instant tournamentStart = dto.getTournamentStartDate();
LocalDate localDate1 = LocalDateTime.ofInstant(tournamentStart,
ZoneOffset.UTC).toLocalDate();
Date.Builder dateBuilder1 = Date.newBuilder();
dateBuilder1.setYear(localDate1.getYear());
dateBuilder1.setMonth(localDate1.getMonthValue());
dateBuilder1.setDay(localDate1.getDayOfMonth());
TournamentCompleteData.Date trnamntStartDate = dateBuilder1.build();
TournamentRecord tr = TournamentRecord.newBuilder()
.setId(dto.getTournamentTypeId())
.setStart(trnamntStartDate)
.setPrize(dto.getFirstPrize())
.setName(dto.getTournamentName())
.setStatus(dto.getStatusName())
.build();
return tr;
}
I have written a test-case which can access this end-point & print the tournaments. But Swift client gets null when it invokes this end point. Already existing protobuf end points work fine with swift client & I have a ProtobufHttpMessageConverter already configured
#Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
And when the swift client invokes the end point, log messages get printed. That means client is invoking the end-point.
Here is the swift client code snippet for LobbyAPI:
import Foundation
class LobbyAPI: Api {
func getTournammentTableList(completion: #escaping ((TournamentFilterPackage_TournamentData?, Error?) -> Void)) {
getData(WithUrl: (APIConstants.lobbyURL) + "tournaments/completedata/", APIKey: APIConstants.apiKey, completion: completion)
}
For TournamentTableListVM
import Cocoa
import RealmSwift
class TournamentTableListVM: NSObject {
private weak var tblListView: LobbyTableListView!
private var tblPreviewVM: TablePreviewVM!
var arrFilterTableList: [LobbyFilterPackage_LobbyTableRecord] = []
var arrTableList: [LobbyFilterPackage_LobbyTableRecord] = []
var timer = Timer()
var didSelectTable: ((_ tableRecord: LobbyFilterPackage_LobbyTableRecord,_ isObserver:Bool) -> Void)!
var getFilterCallBack:(() -> Void)?
var currentSelectedMoneyType: (() -> TabMenuMoneyToggleView.Money) = { .play }{
didSet{
tblPreviewVM.currentSelectedMoneyType = currentSelectedMoneyType
}
}
var didTakeActionFromTablePreview: ((TablePreviewVM.TablePreviewPlayerActionType, Int) -> Void)?
//For sorting
var currentSortKey: String?
var currentSortAscending: Bool?
var aUserData: APPokerProto_PlayerProfileProto!
var observClick = false
func getCompleteTableData() {
LobbyAPI().getTournammentTableList() {[weak self] (aTournammentData, aError) in
guard let self = self else { return }
guard aError == nil, let tableData = aTournammentData, tableData.lobbyTableRecords.count > 0 else {
self.emptyTableAndPreview()
LoginManager.shared.didToggleNotify()
return
}
LoginManager.shared.didToggleNotify()
self.arrFilterTableList = tableData.lobbyTableRecords
self.arrTableList = tableData.lobbyTableRecords
self.tblListView.tblList.reloadData()
self.tblListView.tblList.selectRowIndexes(NSIndexSet.init(index: 0) as IndexSet, byExtendingSelection: true)
self.timeStamp = String(tableData.timeStamp.seconds)
}
}
In this above code "aTournammentData" is coming as nil.
Update Found that in front end swift, it was mapped to wrong generated swift struct. With the help of https://github.com/apple/swift-protobuf plugin TournamentCompleteData.pb.swift file was generated as below
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: TournamentCompleteData.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
struct TournamentFilterPackage_TournamentData {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var tournamentRecords: [TournamentFilterPackage_TournamentRecord] = []
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
struct TournamentFilterPackage_TournamentRecord {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
var id: Int64 = 0
var start: TournamentFilterPackage_Date {
get {return _start ?? TournamentFilterPackage_Date()}
set {_start = newValue}
}
/// Returns true if `start` has been explicitly set.
var hasStart: Bool {return self._start != nil}
/// Clears the value of `start`. Subsequent reads from it will return its default value.
mutating func clearStart() {self._start = nil}
var prize: Float = 0
var name: String = String()
var speed: String = String()
var type: String = String()
var buyIn: Float = 0
var noOfParticipants: Int32 = 0
var status: String = String()
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
fileprivate var _start: TournamentFilterPackage_Date? = nil
}
struct TournamentFilterPackage_Date {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// Year of the date. Must be from 1 to 9999, or 0 to specify a date without
/// a year.
var year: Int32 = 0
/// Month of a year. Must be from 1 to 12, or 0 to specify a year without a
/// month and day.
var month: Int32 = 0
/// Day of a month. Must be from 1 to 31 and valid for the year and month, or 0
/// to specify a year by itself or a year and month where the day isn't
/// significant.
var day: Int32 = 0
var unknownFields = SwiftProtobuf.UnknownStorage()
init() {}
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "TournamentFilterPackage"
extension TournamentFilterPackage_TournamentData: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".TournamentData"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "tournamentRecords"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeRepeatedMessageField(value: &self.tournamentRecords) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.tournamentRecords.isEmpty {
try visitor.visitRepeatedMessageField(value: self.tournamentRecords, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: TournamentFilterPackage_TournamentData, rhs: TournamentFilterPackage_TournamentData) -> Bool {
if lhs.tournamentRecords != rhs.tournamentRecords {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension TournamentFilterPackage_TournamentRecord: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".TournamentRecord"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "id"),
2: .same(proto: "start"),
3: .same(proto: "prize"),
4: .same(proto: "name"),
5: .same(proto: "speed"),
6: .same(proto: "type"),
7: .same(proto: "buyIn"),
8: .same(proto: "noOfParticipants"),
9: .same(proto: "status"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularInt64Field(value: &self.id) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._start) }()
case 3: try { try decoder.decodeSingularFloatField(value: &self.prize) }()
case 4: try { try decoder.decodeSingularStringField(value: &self.name) }()
case 5: try { try decoder.decodeSingularStringField(value: &self.speed) }()
case 6: try { try decoder.decodeSingularStringField(value: &self.type) }()
case 7: try { try decoder.decodeSingularFloatField(value: &self.buyIn) }()
case 8: try { try decoder.decodeSingularInt32Field(value: &self.noOfParticipants) }()
case 9: try { try decoder.decodeSingularStringField(value: &self.status) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every if/case branch local when no optimizations
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
// https://github.com/apple/swift-protobuf/issues/1182
if self.id != 0 {
try visitor.visitSingularInt64Field(value: self.id, fieldNumber: 1)
}
try { if let v = self._start {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
if self.prize != 0 {
try visitor.visitSingularFloatField(value: self.prize, fieldNumber: 3)
}
if !self.name.isEmpty {
try visitor.visitSingularStringField(value: self.name, fieldNumber: 4)
}
if !self.speed.isEmpty {
try visitor.visitSingularStringField(value: self.speed, fieldNumber: 5)
}
if !self.type.isEmpty {
try visitor.visitSingularStringField(value: self.type, fieldNumber: 6)
}
if self.buyIn != 0 {
try visitor.visitSingularFloatField(value: self.buyIn, fieldNumber: 7)
}
if self.noOfParticipants != 0 {
try visitor.visitSingularInt32Field(value: self.noOfParticipants, fieldNumber: 8)
}
if !self.status.isEmpty {
try visitor.visitSingularStringField(value: self.status, fieldNumber: 9)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: TournamentFilterPackage_TournamentRecord, rhs: TournamentFilterPackage_TournamentRecord) -> Bool {
if lhs.id != rhs.id {return false}
if lhs._start != rhs._start {return false}
if lhs.prize != rhs.prize {return false}
if lhs.name != rhs.name {return false}
if lhs.speed != rhs.speed {return false}
if lhs.type != rhs.type {return false}
if lhs.buyIn != rhs.buyIn {return false}
if lhs.noOfParticipants != rhs.noOfParticipants {return false}
if lhs.status != rhs.status {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension TournamentFilterPackage_Date: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".Date"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "year"),
2: .same(proto: "month"),
3: .same(proto: "day"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularInt32Field(value: &self.year) }()
case 2: try { try decoder.decodeSingularInt32Field(value: &self.month) }()
case 3: try { try decoder.decodeSingularInt32Field(value: &self.day) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.year != 0 {
try visitor.visitSingularInt32Field(value: self.year, fieldNumber: 1)
}
if self.month != 0 {
try visitor.visitSingularInt32Field(value: self.month, fieldNumber: 2)
}
if self.day != 0 {
try visitor.visitSingularInt32Field(value: self.day, fieldNumber: 3)
}
try unknownFields.traverse(visitor: &visitor)
}
static func ==(lhs: TournamentFilterPackage_Date, rhs: TournamentFilterPackage_Date) -> Bool {
if lhs.year != rhs.year {return false}
if lhs.month != rhs.month {return false}
if lhs.day != rhs.day {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

How can I build a recursive function in Swift to return a String?

I have a Node class defined as follows. value: T is a String
class Node<T> {
var value: T
weak var parent: Node?
var children = [Node<T>]()
init(_ value: T) {
self.value = value
}
func add(_ node: Node<T>) {
children.append(node)
node.parent = self
}
}
I'd like to build a function to return a String of the current Node's value and all Parent values. Ideally, the function would be defined in the class. For example,
currentnode.listAllValues()
would return -> "/parent2value/parent1value/currentnodevalue"
So far the following function works with a simple print(), and I've also considered using an inout parameter.
func listAllValues(node: Node<String>) {
print(node.value)
if node.parent?.value != nil {
listAllValues(node: node.parent!)
}
}
You can achieve this with an instance method which calls itself on the parent node first, if there is one:
func listAllValues() -> String {
if let p = parent {
return "\(p.listAllValues())/\(value)"
} else {
return "/\(value)"
}
}
Or as an obfuscated one-liner:
func listAllValues() -> String {
return "\(parent?.listAllValues() ?? "")/\(value)"
}
Example:
let p2 = Node("parent2value")
let p1 = Node("parent1value") ; p2.add(p1)
let n = Node("currentNodeValue") ; p1.add(n)
print(n.listAllValues())
// --> /parent2value/parent1value/currentNodeValue
Here you go:
func desc(_ s:String? = nil) -> String {
var me = String(describing:self.value)
if let prev = s {
me += "/" + prev
}
return self.parent?.desc(me) ?? me
}
Example:
let n = Node("hey")
n.add(Node("ho"))
n.children.first?.add(Node("nonny nonny no"))
let start = n.children.first!.children.first!
print(start.desc())

declare generic class with a generic class as a parameter in swift

I wrote these simple generic classes and it worked great:
class LinkedListNode <T> {
var value: T
var next: LinkedListNode<T>?
weak var prev: LinkedListNode<T>?
init(value: T) {
self.value = value
self.next = nil
}
}
class LinkedList<T> {
var first: LinkedListNode<T>? = nil
var last: LinkedListNode<T>? = nil
var count = 0
#discardableResult func append(_ value: T) -> LinkedListNode<T> {
let new = LinkedListNode(value: value)
new.prev = last
last?.next = new
count += 1
last = new
if first == nil {
first = new
}
return new
}
}
And I used it like:
let list = LinkedList<Int>()
list.append(3)
let lastNode = list.append(5)
Now I realized there are some cases when I need to have a customized node: CustomNode<T>, subclass of LinkedListNode<T>. So I would like to be able to pass the class to be used as the node as:
let list = LinkedList<CustomNode<Int>>()
list.append(3)
let customNode = list.append(5)
How can I declare my class to have it like this or something similar?
I have tried the following declaration but weird errors rise. Is this even possible?
class LinkedList<Node<T>: LinkedListNode<T>> { ...
Update 2019/07/26.
Even with Kamran's approach this method does not compile. I am not sure if this is doable without a protocol. See my comment on Kamran's answer.
func remove(node: LinkedListNode<T>) { // change to `func remove(node: U)`
node.next?.prev = node.prev
node.prev?.next = node.next
if node === first {
first = first?.next
}
if node === last {
last = last?.prev // Error here: "Cannot assign value of LinkedListNode<T>? to U?"
}
}
The syntax you are trying can be achieved as below,
class LinkedListNode <T> {
var value: T
var next: LinkedListNode<T>?
weak var prev: LinkedListNode<T>?
required init(value: T) {
self.value = value
self.next = nil
}
}
class GenericCustomNode<T>: LinkedListNode<T> {
required init(value: T) {
super.init(value: value)
}
}
class NonGenericCustomNode: LinkedListNode<Int> {
required init(value: Int) {
super.init(value: value)
}
}
class LinkedList<T, U: LinkedListNode<T>> {
var first: U? = nil
var last: U? = nil
var count = 0
#discardableResult func append(_ value: T) -> U {
let new = U(value: value)
new.prev = last
last?.next = new
count += 1
last = new
if first == nil {
first = new
}
return new
}
func remove(node: U) {
node.next?.prev = node.prev
node.prev?.next = node.next
if node === first {
first = first?.next as? U
}
if node === last {
last = last?.prev as? U
}
}
}
Usage:
let list = LinkedList<Int, LinkedListNode<Int>>()
list.append(5)
print(list.first?.value)
let someCustom = LinkedList<Int, GenericCustomNode<Int>>()
someCustom.append(15)
print(someCustom.first?.value)
let otherCustom = LinkedList<Int, NonGenericCustomNode>()
otherCustom.append(2)
print(otherCustom.first?.value)
Output:
Optional(5)
Optional(15)
Optional(2)
You will need to define a protocol with an associated type:
protocol Node: class {
associatedtype Value
var value: Value {get set}
var next: Self? {get set}
var prev: Self? {get set}
init(value: Value)
}
final class BasicNode<Value>: Node {
var value: Value
var next: BasicNode<Value>?
weak var prev: BasicNode<Value>?
init(value: Value) {
self.value = value
}
}
final class CustomNode<Value>: Node {
// customize however you want
var value: Value
var next: BasicNode<Value>?
weak var prev: BasicNode<Value>?
init(value: Value) {
self.value = value
}
}
class LinkedList<N: Node> {
var first: N? = nil
var last: N? = nil
var count = 0
#discardableResult
func append(_ value: N.Value) -> N {
let new = N(value: value)
new.prev = last
last?.next = new
count += 1
last = new
if first == nil {
first = new
}
return new
}
}
However, this will require using your basic linked list in an annoying way all the time:
let list = LinkedList<BasicNode<Int>>()
Depending on how you need to customize the node, I would consider finding a way to customize the behavior in the LinkList class itself using dependency injection.

How to remove duplicate characters from a string in Swift

ruby has the function string.squeeze, but I can't seem to find a swift equivalent.
For example I want to turn bookkeeper -> bokepr
Is my only option to create a set of the characters and then pull the characters from the set back to a string?
Is there a better way to do this?
Edit/update: Swift 4.2 or later
You can use a set to filter your duplicated characters:
let str = "bookkeeper"
var set = Set<Character>()
let squeezed = str.filter{ set.insert($0).inserted }
print(squeezed) // "bokepr"
Or as an extension on RangeReplaceableCollection which will also extend String and Substrings as well:
extension RangeReplaceableCollection where Element: Hashable {
var squeezed: Self {
var set = Set<Element>()
return filter{ set.insert($0).inserted }
}
}
let str = "bookkeeper"
print(str.squeezed) // "bokepr"
print(str[...].squeezed) // "bokepr"
I would use this piece of code from another answer of mine, which removes all duplicates of a sequence (keeping only the first occurrence of each), while maintaining order.
extension Sequence where Iterator.Element: Hashable {
func unique() -> [Iterator.Element] {
var alreadyAdded = Set<Iterator.Element>()
return self.filter { alreadyAdded.insert($0).inserted }
}
}
I would then wrap it with some logic which turns a String into a sequence (by getting its characters), unqiue's it, and then restores that result back into a string:
extension String {
func uniqueCharacters() -> String {
return String(self.characters.unique())
}
}
print("bookkeeper".uniqueCharacters()) // => "bokepr"
Here is a solution I found online, however I don't think it is optimal.
func removeDuplicateLetters(_ s: String) -> String {
if s.characters.count == 0 {
return ""
}
let aNum = Int("a".unicodeScalars.filter{$0.isASCII}.map{$0.value}.first!)
let characters = Array(s.lowercased().characters)
var counts = [Int](repeatElement(0, count: 26))
var visited = [Bool](repeatElement(false, count: 26))
var stack = [Character]()
var i = 0
for character in characters {
if let num = asciiValueOfCharacter(character) {
counts[num - aNum] += 1
}
}
for character in characters {
if let num = asciiValueOfCharacter(character) {
i = num - aNum
counts[i] -= 1
if visited[i] {
continue
}
while !stack.isEmpty, let peekNum = asciiValueOfCharacter(stack.last!), num < peekNum && counts[peekNum - aNum] != 0 {
visited[peekNum - aNum] = false
stack.removeLast()
}
stack.append(character)
visited[i] = true
}
}
return String(stack)
}
func asciiValueOfCharacter(_ character: Character) -> Int? {
let value = String(character).unicodeScalars.filter{$0.isASCII}.first?.value ?? 0
return Int(value)
}
Here is one way to do this using reduce(),
let newChar = str.characters.reduce("") { partial, char in
guard let _ = partial.range(of: String(char)) else {
return partial.appending(String(char))
}
return partial
}
As suggested by Leo, here is a bit shorter version of the same approach,
let newChar = str.characters.reduce("") { $0.range(of: String($1)) == nil ? $0.appending(String($1)) : $0 }
Just Another solution
let str = "Bookeeper"
let newChar = str.reduce("" , {
if $0.contains($1) {
return "\($0)"
} else {
return "\($0)\($1)"
}
})
print(str.replacingOccurrences(of: " ", with: ""))
Use filter and contains to remove duplicate values
let str = "bookkeeper"
let result = str.filter{!result.contains($0)}
print(result) //bokepr

get the type/class of a property from its name in swift

Lets say I have this class:
class Node {
var value: String
var children: [Node]?
}
If I have the name of one of its properties (for example "children") how can I get its type? (In this case [Node]?)
I imagine having a global function like below will solve my needs:
func typeOfPropertyWithName(name: String, ofClass: AnyClass) -> AnyClass? {
//???
}
// Example usage:
var arrayOfNodesClass = typeOfPropertyWithName("children", Node.self)
Swift 2 (Note: Reflection changed):
import Foundation
enum PropertyTypes:String
{
case OptionalInt = "Optional<Int>"
case Int = "Int"
case OptionalString = "Optional<String>"
case String = "String"
//...
}
extension NSObject{
//returns the property type
func getTypeOfProperty(name:String)->String?
{
let type: Mirror = Mirror(reflecting:self)
for child in type.children {
if child.label! == name
{
return String(child.value.dynamicType)
}
}
return nil
}
//Property Type Comparison
func propertyIsOfType(propertyName:String, type:PropertyTypes)->Bool
{
if getTypeOfProperty(propertyName) == type.rawValue
{
return true
}
return false
}
}
custom class:
class Person : NSObject {
var id:Int?
var name : String?
var email : String?
var password : String?
var child:Person?
}
get the type of the "child" property:
let person = Person()
let type = person.getTypeOfProperty("child")
print(type!) //-> Optional<Person>
property type checking:
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalInt) ) //--> false
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalString) //--> true
or
if person.propertyIsOfType("email", type: PropertyTypes.OptionalString)
{
//true -> do something
}
else
{
//false -> do something
}
Reflection is achieved in Swift using the global reflect() function. When passing an instance of some type to reflect() it returns a MirrorType, which has a range of properties allowing you to analyze your instance:
var value: Any { get }
var valueType: Any.Type { get }
var objectIdentifier: ObjectIdentifier? { get }
var count: Int { get }
var summary: String { get }
var quickLookObject: QuickLookObject? { get }
var disposition: MirrorDisposition { get }
subscript(i: Int) -> (String, MirrorType) { get }
This seems to work:
func getTypeOfVariableWithName(name: String, inInstance instance: Any) -> String? {
let mirror = reflect(instance)
var variableCollection = [String: MirrorType]()
for item in 0..<mirror.count {
variableCollection[mirror[item].0] = mirror[item].1
}
if let type = variableCollection[name] {
let longName = _stdlib_getDemangledTypeName(type.value)
let shortName = split(longName, { $0 == "."}).last
return shortName ?? longName
}
return nil
}
Here's some example code on SwiftStub.
Edit:
The result for optional values is only "Optional".
The result for arrays is only "Array".
The result for dictionaries is only "Dictionary".
I'm not sure if it is possible to extract what kind of optional/array/dictionary it is. But I guess this would also be the case for custom data structures using generics.
Building on #PeterKreinz answer I needed to be able to check types of inherited properties as well so added a little to his above code:
extension NSObject {
// Returns the property type
func getTypeOfProperty (name: String) -> String? {
var type: Mirror = Mirror(reflecting: self)
for child in type.children {
if child.label! == name {
return String(child.value.dynamicType)
}
}
while let parent = type.superclassMirror() {
for child in parent.children {
if child.label! == name {
return String(child.value.dynamicType)
}
}
type = parent
}
return nil
}
}
Hope this may help someone.
Swift 3 update:
// Extends NSObject to add a function which returns property type
extension NSObject {
// Returns the property type
func getTypeOfProperty (_ name: String) -> String? {
var type: Mirror = Mirror(reflecting: self)
for child in type.children {
if child.label! == name {
return String(describing: type(of: child.value))
}
}
while let parent = type.superclassMirror {
for child in parent.children {
if child.label! == name {
return String(describing: type(of: child.value))
}
}
type = parent
}
return nil
}
}
The solution provided by #peter-kreinz using Swift's class Mirror works beautifully when you have an instance of a class, and want to know the types of the properties. However if you want to inspect the properties of a class without having an instance of it you might be interested in my solution.
I have a solution that finds the name and type of a property given any class that inherits from NSObject.
I wrote a lengthy explanation on StackOverflow here, and my project is available here on Github,
In short you can do something like this (but really check out the code Github):
public class func getTypesOfProperties(inClass clazz: NSObject.Type) -> Dictionary<String, Any>? {
var count = UInt32()
guard let properties = class_copyPropertyList(clazz, &count) else { return nil }
var types: Dictionary<String, Any> = [:]
for i in 0..<Int(count) {
guard let property: objc_property_t = properties[i], let name = getNameOf(property: property) else { continue }
let type = getTypeOf(property: property)
types[name] = type
}
free(properties)
return types
}