While i were changing kotlin code to swift code. I had a problem with create abstract immutable list.
private interface A{
val Id : Int
val anotherValue : Int
}
private val anotherList : ArrayList<A>
override val idList: List<Int>
get() = object : AbstractList<Int>() {
override val size: Int
get() = anotherList.size
override fun get(index: Int): Int {
return anotherList[index].Id
}
}
This code is create 'AbstractList' on call the 'idList' property. I intended not to take up any additional capacity except for the created instance's own.
I tried to migrating code as follows at Swift:
override var idList: [Int]{
return self.anotherList.map{
$0.Id
}
}
However, this code takes up more memory, such as List Copy. How can i do?
You could use a lazy map:
let idList: LazyMapSequence<[A], Int> {
self.anotherList.lazy.map(\.id)
}
I am pretty sure lazy gives you a lazy "view" of the array. And since this is a lazy sequence, the ids won't be computed until you need them. Also, because arrays are random access, if you need, say, the third id, the first and second id won't be computed.
Alternatively, and I think this is better, write your own ArrayKeyPathView collection:
struct ArrayKeyPathView<WrappedElement, KeyPathType> : RandomAccessCollection {
subscript(position: Int) -> Element {
get {
wrapped[position][keyPath: keyPath]
}
}
var startIndex: Int {
wrapped.startIndex
}
var endIndex: Int {
wrapped.endIndex
}
var indices: Range<Int> {
wrapped.indices
}
typealias Index = Int
typealias SubSequence = ArrayKeyPathView
typealias Element = KeyPathType
typealias Indices = Range<Int>
private let wrapped: [WrappedElement]
private let keyPath: KeyPath<WrappedElement, KeyPathType>
init(_ array: [WrappedElement], keyPath: KeyPath<WrappedElement, KeyPathType>) {
self.wrapped = array
self.keyPath = keyPath
}
}
Usage:
let idList: ArrayKeyPathView<A, Int> {
ArrayKeyPathView(self.anotherList, keyPath: \.id)
}
Since swift arrays are copy-on-write, just passing it to ArrayKeyPathView doesn't create a copy.
Related
I have list of objects T and I want to calculate their sum (T objects)
var objects: Observable<List<T>>
T object has a method which return Int value.
The main idea to get each object and prepare array of values (flatMap function). The next step will be reduce func with Int values.
let sum = values.reduce(0) { $0 + $1 }
Q: How to get each T object?
Have a look at the solution below which is trying to demonstrate what you are trying to do, you might need a protocol for type T that has int property like the example below. You can try it with playground.
protocol Countable {
var value: Int { get }
init(value: Int)
}
class User: Countable {
var value: Int = 0
required convenience init(value: Int) {
self.init()
self.value = value
}
}
class UserGroup<T: Countable> {
func calculateTotal() {
let users: [T] = [T(value: 2), T(value: 21)]
let total = users.flatMap { ($0 as Countable).value }.reduce(0) { $0 + $1 }
print("total", total)
}
}
let userGroup = UserGroup<User>()
userGroup.calculateTotal()
I have a custom class defined as follows :
class DisplayMessage : NSObject {
var id : String?
var partner_image : UIImage?
var partner_name : String?
var last_message : String?
var date : NSDate?
}
Now I have an array myChats = [DisplayMessage]?. The id field is unique for each DisplayMessage object. I need to check my array and remove all duplicates from it, essentially ensure that all objects in the array have a unique id. I have seen some solutions using NSMutableArray and Equatable however I'm not sure how to adapt them here; I also know of Array(Set(myChats)) however that doesn't seem to work for an array of custom objects.
Here is an Array extension to return the unique list of objects based on a given key:
extension Array {
func unique<T:Hashable>(map: ((Element) -> (T))) -> [Element] {
var set = Set<T>() //the unique list kept in a Set for fast retrieval
var arrayOrdered = [Element]() //keeping the unique list of elements but ordered
for value in self {
if !set.contains(map(value)) {
set.insert(map(value))
arrayOrdered.append(value)
}
}
return arrayOrdered
}
}
for your example do:
let uniqueMessages = messages.unique{$0.id ?? ""}
You can do it with a set of strings, like this:
var seen = Set<String>()
var unique = [DisplayMessage]
for message in messagesWithDuplicates {
if !seen.contains(message.id!) {
unique.append(message)
seen.insert(message.id!)
}
}
The idea is to keep a set of all IDs that we've seen so far, go through all items in a loop, and add ones the IDs of which we have not seen.
Here is an Array extension to return the unique list of objects based on a keyPath:
extension Array {
func uniques<T: Hashable>(by keyPath: KeyPath<Element, T>) -> [Element] {
return reduce([]) { result, element in
let alreadyExists = (result.contains(where: { $0[keyPath: keyPath] == element[keyPath: keyPath] }))
return alreadyExists ? result : result + [element]
}
}
}
Usage:
myChats.uniques(by: \.id)
Create a free duplicate version of an Array, using equality comparisons based on a given key
public extension Sequence {
public func uniq<Id: Hashable >(by getIdentifier: (Iterator.Element) -> Id) -> [Iterator.Element] {
var ids = Set<Id>()
return self.reduce([]) { uniqueElements, element in
if ids.insert(getIdentifier(element)).inserted {
return uniqueElements + CollectionOfOne(element)
}
return uniqueElements
}
}
public func uniq<Id: Hashable >(by keyPath: KeyPath<Iterator.Element, Id>) -> [Iterator.Element] {
return self.uniq(by: { $0[keyPath: keyPath] })
}
}
public extension Sequence where Iterator.Element: Hashable {
var uniq: [Iterator.Element] {
return self.uniq(by: { (element) -> Iterator.Element in
return element
})
}
}
Usage
let numbers = [1,2,3,4,5,6,7,1,1,1,]
let cars = [Car(id:1), Car(id:1), Car(id:2)]
numbers.uniq
cars.uniq(by: { $0.id})
cars.uniq(by: \Car.id)
cars.uniq(by: \.id)
protocol ParentProtocol { }
protocol ChildProtocol: ParentProtocol { }
protocol Child_With_Value_Protocol: ParentProtocol {
associatedType Value
func retrieveValue() -> Value
}
Attempting to create a single array of type ParentProtocol that contains both ChildProtocol and Child_With_Value_Protocol. Is there any possible way to create a function that loops through the heterogeneous array and returns the values of just type Child_With_Value_Protocol?
This may require an architecture change. Open to all solutions.
Attempted Failed Solution #1
var parents: [ParentProtocol] = [...both ChildProtocol & Child_With_Value_Protocol...]
func retrieveValues() -> [Any] {
var values = [Any]()
for parent in parents {
if let childWithValue = parent as? Child_With_Value_Protocol { // Fails to compile
values.append(childWithValue.retrieveValue())
}
}
return values
}
This fails with an error of protocol 'Child_With_Value_Protocol' can only be used as a generic constraint because it has Self or associated type requirements which makes sense since the compiler would not know the type when converted to just Child_With_Value_Protocol, this leads to the next failed solution.
Attempted Failed Solution #2
If the array was a homogeneous array of just Child_With_Value_Protocol, type erasing could be used to retrieve the values.
var parents: [ParentProtocol] = [...both ChildProtocol & Child_With_Value_Protocol...]
struct AnyValue {
init<T: Child_With_Value_Protocol>(_ protocol: T) {
_retrieveValue = protocol.retrieveValue as () -> Any
}
func retrieveValue() -> Any { return _retrieveValue() }
let _retrieveValue: () -> Any
}
func retrieveValues() -> [Any] {
var values = [Any]()
for parent in parents {
values.append(AnyValue(parent).retrieveValue()) // Fails to compile
}
return values
}
This fails to compile due to the fact that the struct AnyValue has no initializer for the ParentProtocol.
Attempted Failed Solution #3
struct AnyValue {
init<T: Child_With_Value_Protocol>(_ protocol: T) {
_retrieveValue = protocol.retrieveValue as () -> Any
}
func retrieveValue() -> Any { return _retrieveValue() }
let _retrieveValue: () -> Any
}
var erased: [AnyValue] = [AnyValue(...), AnyValue(...), AnyValue(...)]
func retrieveValues() -> [Any] {
var values = [Any]()
for value in erased {
values.append(value.retrieveValue())
}
return values
}
Unlike the other solutions, this solution actually compiles. Problem with this solution resides in the fact that the array erased can only hold values of the type-erased versions of Child_With_Value_Protocol. The goal is for the array to hold types of both Child_With_Value_Protocol and ChildProtocol.
Attempted Failed Solution #4
Modifying the type-erase struct to include an initializer for ParentProtocol still creates a solution that compiles, but then the struct will only use the less specific init, instead of the more specific init.
struct AnyValue {
init?<T: ParentProtocol>(_ protocol: T) {
return nil
}
init?<T: Child_With_Value_Protocol>(_ protocol: T) {
_retrieveValue = protocol.retrieveValue as () -> Any
}
func retrieveValue() -> Any { return _retrieveValue() }
let _retrieveValue: (() -> Any)?
}
The prior comments are likely right. Nevertheless, you could box the variants in an enum and create an array of those. The reference would then switch on the enum value, each having associated data of the right type
EDIT: I didn't bother with the associatedValue, because it seems irrelevant to the question being asked. The following works in a playground:
protocol ParentProtocol: CustomStringConvertible {
static func retrieveValues(parents: [FamilyBox]) -> [ParentProtocol]
}
protocol ChildProtocol: ParentProtocol { }
protocol Other_Child_Protocol: ParentProtocol { }
enum FamilyBox {
case Parent(parent: ParentProtocol)
case Child(child: ChildProtocol)
case OtherChildProtocol(withValue: Other_Child_Protocol)
}
var parents: [FamilyBox] = []
struct P: ParentProtocol {
var description: String { return "Parent" }
static func retrieveValues(parents: [FamilyBox]) -> [ParentProtocol] {
var values = [ParentProtocol]()
for parent in parents {
switch parent {
case .Parent(let elementValue):
values.append(elementValue)
default:
break;
}
}
return values
}
}
struct C: ChildProtocol {
var description: String { return "Child" }
static func retrieveValues(parents: [FamilyBox]) -> [ParentProtocol] {
var values = [ParentProtocol]()
for parent in parents {
switch parent {
case .Child(let elementValue):
values.append(elementValue)
default:
break;
}
}
return values
}
}
struct CV: Other_Child_Protocol {
var description: String { return "Other Child" }
static func retrieveValues(parents: [FamilyBox]) -> [ParentProtocol] {
var values = [ParentProtocol]()
for parent in parents {
switch parent {
case .OtherChildProtocol(let elementValue):
values.append(elementValue)
default:
break;
}
}
return values
}
}
let p = FamilyBox.Parent(parent: P())
let c = FamilyBox.Child(child: C())
let cv = FamilyBox.OtherChildProtocol(withValue: CV())
let array:[FamilyBox] = [p, c, cv]
print(P.retrieveValues(array))
print(C.retrieveValues(array))
print(CV.retrieveValues(array))
The prints from the last three lines are:
[Parent]
[Child]
[Other Child]
While I'm sure it can be improved, I think that meets the original intent. No?
I'm new to Swift and iOS programming.
I'm trying to test out a simple algorithm and need an array of Stacks. Don't have to be anything fancy (Stacks of Ints will do).
I got the Stack implementation from The Swift Programming Language documentation:
struct IntStack {
var items = [Int]()
mutating func push(item: Int) {
items.append(item)
}
mutating func pop() -> Int {
return items.removeLast()
}
mutating func count() -> Int {
return items.count
}
mutating func show() {
println(items)
}
}
The count and show functions are my contribution. But when I try to declare an array of Stacks I get an error...
var lines = IntStack()[5]
"IntStack" does not have a member named subscript
I'm guessing it has something to do with Optionals but can figure out what it is.
Any help?
Details
Swift 5.1, Xcode 11.3.1
Generic Stack Implementation
Stackable protocol
protocol Stackable {
associatedtype Element
func peek() -> Element?
mutating func push(_ element: Element)
#discardableResult mutating func pop() -> Element?
}
extension Stackable {
var isEmpty: Bool { peek() == nil }
}
Stack
struct Stack<Element>: Stackable where Element: Equatable {
private var storage = [Element]()
func peek() -> Element? { storage.last }
mutating func push(_ element: Element) { storage.append(element) }
mutating func pop() -> Element? { storage.popLast() }
}
extension Stack: Equatable {
static func == (lhs: Stack<Element>, rhs: Stack<Element>) -> Bool { lhs.storage == rhs.storage }
}
extension Stack: CustomStringConvertible {
var description: String { "\(storage)" }
}
extension Stack: ExpressibleByArrayLiteral {
init(arrayLiteral elements: Self.Element...) { storage = elements }
}
Usage
var stack = Stack<Int>()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.peek())
print(stack.pop())
print(stack)
print(stack == Stack<Int>())
stack = [3,2,1]
print(stack)
There's no problem with what you're doing there - that's just not the syntax for declaring an array. If you want an array of 5 stacks, you can do this:
[IntStack(), IntStack(), IntStack(), IntStack(), IntStack()]
Or, you can initialise the array like this:
Array(count: 5, repeatedValue: IntStack())
Also, you don't need to mark your functions as mutating unless they actually mutate the structure - so count() and show() don't need it.
It's possible to just extend arrays with stack specific methods. This might or might not be what you want, depending on if you want to disallow array like access.
protocol Stack {
associatedtype Element
mutating func push(item: Element)
// allows discarding the result without generating a warning.
#discardableResult
mutating func pop() -> Element?
func peek() -> Element?
var count: Int { get }
}
extension Array: Stack {
mutating func push(item: Element) {
self.append(item)
}
mutating func pop() -> Element? {
if let last = self.last {
self.remove(at: self.count - 1)
return last
}
return .none
}
func peek() -> Element? {
self.last
}
}
Simple test case:
class StackTests: XCTestCase {
func testExample() throws {
var stack = Array<Int>()
XCTAssertEqual(stack.peek(), .none, "stack is empty, peek returns none")
XCTAssertEqual(stack.pop(), .none, "stack is empty, pop returns none")
stack.push(item: 0)
stack.push(item: 1)
stack.push(item: 2)
XCTAssertEqual(stack.peek(), 2)
XCTAssertEqual(stack.pop(), 2)
XCTAssertEqual(stack.peek(), 1)
XCTAssertEqual(stack.pop(), 1)
XCTAssertEqual(stack.peek(), 0)
XCTAssertEqual(stack.pop(), 0)
}
}
There is no need to declare the size of the stack when you init it. Jus calling this should be enough.
var lines = IntStack()
Also note that your count() and show() methods should not be mutating since they don't modify the struct in any way.
Just look into this code. Stack example with generic data type and without using the array.
class Node<T>: CustomStringConvertible {
let value: T
var next: Node?
var description: String {
guard let next = next else { return "\(value)" }
return "\(value)\n" + String(describing: next)
}
init(value: T) {
self.value = value
}
}
// Stack class to hold all items
class Stack<T>: CustomStringConvertible {
var top: Node<T>?
var description: String {
guard let top = top else { return "---- Stack is EMPTY ----" }
return "---- Stack Begin ----\n" + String(describing: top) + "\n---- Stack End ----"
}
// push
func push(_ value: T) {
let currentTop = top
top = Node(value: value)
top?.next = currentTop
}
#discardableResult
func pop() -> T? {
let currentTop = top
top = top?.next
return currentTop?.value
}
#discardableResult
func peek() -> T? {
return top?.value
}
}
Excellent implementation! One thought: I think it should be:
func peek() -> Element? { storage.last }
Here is a Stack implementation using Swift Generics,
struct Fruit {
let fruitName : String
let color : String
init(_ name: String,_ color: String) {
self.fruitName = name
self.color = color
}
}
let fruit1 = Fruit("Apple", "Red")
let fruit2 = Fruit("Grapes", "Green")
let fruitStack = Stack<Fruit>()
fruitStack.push(fruit1)
fruitStack.push(fruit2)
let fruitFfromStack = fruitStack.pop()
print("Fruit popped from Stack, Name : \(String(describing: fruitFfromStack?.fruitName)) ,Color : \(String(describing: fruitFfromStack?.color))")
let fruitFfromStack1 = fruitStack.pop()
print("Fruit popped from Stack, Name : \(String(describing: fruitFfromStack1?.fruitName)) ,Color : \(String(describing: fruitFfromStack1?.color))")
Full code is here :
https://reactcodes.blogspot.com/2019/01/generic-stack-implementation-with.html
I defined two types as follow: I want to define a function 'matches' that compares two KeyTypePairs and returns true or false depends on matching on key and type.
protocol KeyTypePair: Hashable {
typealias val
var key: String { get }
var type: Any.Type { get }
}
public struct KeyTypePairOf<T>: KeyTypePair {
typealias val = T
let _key: String
let _type: Any.Type
public var key: String {
get {
return _key
}
}
public var type: Any.Type {
get {
return _type
}
}
public var hashValue: Int {
get {
return _key.hashValue
}
}
public init(key: String) {
self._key = key
self._type = T.self
}
init<T: KeyTypePair>(property: T) {
self._key = pair.key
self._type = pair.type
}
func matches<T: KeyTypePair>(pair:T) -> Bool {
let x = self._type == pair.type // invalid, how do I check equal types?
return self._key == pair.key && x
}
}
How do I compare the 'types' of the struct? Been a headache. Should I use AnyObject instead?
I tested this in a Swift 4 playground
struct Foo {}
struct Bar {}
let fooType: Any.Type = Foo.self
let barType: Any.Type = Bar.self
fooType == Foo.self // true
fooType is Foo.Type // true
fooType == barType // false
The tool you want is object_getClassName (which returns a String). Right now, you can't directly compare types. This feels like just a missing compiler feature rather than anything deep about swift. You'd think you could compare x.dynamicType == y.dynamicType, but that doesn't currently work. See also What is the pattern for entities and Equatable?