How to remove duplicate data in the UIPickerView in Swift - swift

May I know how to remove the duplicate data which all the data is passing from the Parse database. I just select one column and pass that column data to this picker view.
I've try to find the query.wherekey but it didn't have the DISTINCT function which similar to the SQL statement, so what should I do to avoid the data duplication?

As you add items one by one into your self.pickerString array, just verify if this array contains or not the new value before addObject new value to the array. For example:
if !self.pickerString.contains(object["Intake"] as! String) {
self.pickerString.append(object["Intake"] as! String)
}
There is no built-in function to remove duplicate items in an array in swift (correct me if I'm wrong). However, you can add new features for array with 'extension' keyword:
extension Array {
func distinct<T: Equatable>() -> [T] {
var newArray = [T]()
for item in self {
if !contains(newArray, item as! T) {
newArray.append(item as! T)
}
}
return newArray
}
}
usage:
let s = ["344","333","1","2","333"]
var p = s.distinct() as [String]

I don't think you have anything like distinct on Parse, you'll have to download all rows and then filter out equal values.
For a functional approach:
func distinct<T: Equatable>(source: [T]) -> [T] {
var unique = [T]()
for item in source {
if !contains(unique, item) {
unique.append(item)
}
}
return unique
}
[...]
self.pickerString = distinct(objects)
[...]

Related

Swift step through dictionary

I was wondering if there's a way to step through a dictionary in Swift. I know I can iterate through, but I was hoping to step one by one through a dictionary of items as the user taps a "next" button.
I was thinking I could initially iterate through the dictionary and store the keys in an array, then step through the keys and retrieve each item as needed, since the array can be indexed. This seems a little inelegant, though. Any thoughts?
My current approach:
var iterator = 0
var keys = [String]()
func loadKeys() {
for (key, value) in items {
keys.append(key)
}
}
func step() {
iterator += 1
let currentKey = keys[iterator]
let currentItem = items[currentKey]
}
I figure it would work just fine, just not sure it's the best practice.
Thanks for your help!
A dictionary also provides you with an iterator, so you can step through it using that:
var iterator = items.makeIterator()
func step() {
if let v = iterator.next() {
let currentKey = v.key
let currentValue = v.value
}
}
A dictionary is an indexed collection, so you can use a dictionary's index to step through the keys and values:
var i = items.startIndex
func step() {
guard i != items.endIndex else {
// at the end of the dictionary
return
}
let (currentKey, currentValue) = items[i]
i = items.index(after: i)
}

How to check if a specific array element contains a specific word?

This function aims to take an array of strings and sort them into two separate arrays—one with elements that contain the word "gold" and one with elements that do not.
The error I get is on line 7 "if i.contains("gold") {". What is the proper way to execute this?
func findgold(_ list: [String]) -> (gold: [String], nogold: [String]) {
var gold = [String]()
var nogold = [String]()
for i in list {
if i.contains("gold") {
gold.append(i)
} else {
nogold.append(i)
}
}
return (gold, nogold)
}
print(findgold(["golden glove", "mold", "ladder", "gold nugget", "taco"]))
contains method was introduced in Swift 3.
Here is solution for Swift 2:
Replace
if i.contains("gold") {
With
if i.rangeOfString("gold") != nil {

Filtering an Array inside a Dictionary - Swift

I am trying to search through a indexed dictionary to return a specific client based on the client's last name. Below are the data structures I am using. Each client object has a name property which is a String.
var clients = Client.loadAllClients() //Returns client array
var contacts = [String: [Client]]() //Indexed clients in a dictionary
var letters: [String] = []
var filteredClient = [Client]()
var shouldShowSearchResults = false
var searchController : UISearchController!
When I do my indexing, the contacts dictionary returns:
{A: [Client("Andrew")]}
Letters array returns:
[A]
I am using the UISearchController to display the filtered array of clients.
func updateSearchResults(for searchController: UISearchController) {
// how to filter the dictionary
self.tableView.reloadData()
}
However, I have no idea how to filter the dictionary to return the correct list of clients. I have tried to use
contacts.filter(isIncluded: ((key: String, value: [Client])) throws -> Bool((key: String, value: [Client])) throws -> Bool)
But I was very confused about the implementation. I am using Xcode 8.0 and Swift 3.0.
If anyone could point me in the right direction, that would be much appreciated. Please let me know if I need to clarify anything. Thank you in advance. The full code can be found at my Github
The main problem is that you are using a dictionary as data source array.
My suggestion is to use a custom struct as model
struct Contact {
let letter : String
var clients : [Client]
init(letter: String, clients : [Client] = [Client]()) {
self.letter = letter
self.clients = clients
}
mutating func add(client : Client) {
clients.append(client)
}
}
Then create your data source array
var contacts = [Contact]()
and the letter array as computed property
var letters : [String] = {
return contacts.map{ $0.letter }
}
It's easy to sort the array by letter
contacts.sort{ $0.letter < $1.letter }
Now you can search / filter this way (text is the text to be searched for)
filteredClient.removeAll()
for contact in contacts {
let filteredContent = contact.clients.filter {$0.name.range(of: text, options: [.anchored, .caseInsensitive, .diacriticInsensitive]) != nil }
if !filteredContent.isEmpty {
filteredClient.append(filteredContent)
}
}
You can even keep the sections (letters) if you declare filteredClient also as [Contact] and create temporary Contact instances with the filtered items.
Of course you need to change all table view data source / delegate methods to conform to the Contact array, but it's worth it. An array as data source is more efficient than a dictionary.

Swift 3: Change item in dictionary

I'm saving lists in a dictionary. These lists need to be updated. But when searching for an item, I need [] operator. When I save the result to a variable, a copy is used. This can not be used, to change the list itself:
item = dicMyList[key]
if item != nil {
// add it to existing list
dicMyList[key]!.list.append(filename)
// item?.list.append(filename)
}
I know, that I need the uncommented code above, but this accesses and searches again in dictionary. How can I save the result, without searching again? (like the commented line)
I want to speed up the code.
In case you needn't verify whether the inner list was actually existing or not prior to adding element fileName, you could use a more compact solution making use of the nil coalescing operator.
// example setup
var dicMyList = [1: ["foo.sig", "bar.cc"]] // [Int: [String]] dict
var key = 1
var fileName = "baz.h"
// "append" (copy-in/copy-out) 'fileName' to inner array associated
// with 'key'; constructing a new key-value pair in case none exist
dicMyList[key] = (dicMyList[key] ?? []) + [fileName]
print(dicMyList) // [1: ["foo.sig", "bar.cc", "baz.h"]]
// same method used for non-existant key
key = 2
fileName = "bax.swift"
dicMyList[key] = (dicMyList[key] ?? []) + [fileName]
print(dicMyList) // [2: ["bax.swift"], 1: ["foo.sig", "bar.cc", "baz.h"]]
Dictionaries and arrays are value types. So if you change an entry you'll need to save it back into the dictionary.
if var list = dicMyList[key] {
list.append(filename)
dicMyList[key] = list
} else {
dicMyList[key] = [filename]
}
It's a little bit late, but you can do something like this:
extension Optional where Wrapped == Array<String> {
mutating func append(_ element: String) {
if self == nil {
self = [element]
}
else {
self!.append(element)
}
}
}
var dictionary = [String: [String]]()
dictionary["Hola"].append("Chau")
You can try this in the Playground and then adapt to your needs.

Swift language: How do I implement a dictionary of array values, and assign (ie. append) new values to the array?

Language: Swift
I declared a dictionary whose value is an array, like this:
var unloadedImagesRows = [String:[Int]]()
private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
print("addToUnloadedImagesRow 0: row: \(row)")
var unloadedRows = imagesRowForLocation(forLocation)
unloadedRows!.append(row)
}
private func imagesRowForLocation(location:String!) -> [Int]! {
var unloadedRows = unloadedImagesRows[location];
if unloadedRows == nil {
unloadedRows = [Int]()
unloadedImagesRows[location] = unloadedRows
}
return unloadedRows
}
private func someMethod() {
addToUnloadedImagesRow(rowIndex, forLocation: event.iconImg)
...
}
The "unloadedRows!.append(row)" works and I saw in my debugger works as I saw the count increased to 1.
However, the next time I retrieve the value as in line "var unloadedRows = unloadedImagesRows[location]", I get a result of an array containing 0 values.
How do I implement a dictionary of array values, and assign (ie. append) new values to the array?
var unloadedRows = imagesRowForLocation(forLocation)
unloadedRows!.append(row)
unloadedImagesRows[forLocation] = unloadedRows!
You retrieve the array by value, i.e. another instance of the array stored inside the dictionary gets created. Therefore you should set it back into the dictionary after appending a value