Sort Swift Code - swift

Who has idea of why this is occurring?
It is giving me error at the Array(places).sorted { $0.1 < $1.1 }.map { $0.0 } part.
let placesByBeacons = [
"12103:16951": [
"Heavenly Sandwiches": 5, // read as: it's 5 meters from
// "Heavenly Sandwiches" to the beacon with
// major 6574 and minor 54631
"Green & Green Salads": 10,
"Mini Panini": 15
],
"648:12": [
"Heavenly Sandwiches": 250,
"Green & Green Salads": 100,
"Mini Panini": 20
],
"17581:4351": [
"Heavenly Sandwiches": 350,
"Green & Green Salads": 500,
"Mini Panini": 170
]
]
func placesNearBeacon(beacon: CLBeacon) -> [String]? {
let beaconKey = "\(beacon.major):\(beacon.minor)"
if let places = self.placesByBeacons[beaconKey] {
let sortedPlaces = Array(places).sorted { $0.1 < $1.1 }.map { $0.0 }
return sortedPlaces
}
return nil
}

You should use sort not sorted. You can also make your function shorter:
func placesNearBeacon(beacon: CLBeacon) -> [String]? {
guard let places = placesByBeacons["\(beacon.major):\(beacon.minor)"] else { return nil }
return places.sort(<).map { $0.0 }
}

Related

How to sort a List using Section by month and year in SwiftUI?

I'm trying something but I could not achieve the result I want and I'm asking for your help because I've struggled a lot.
I have a list of document and I want to display each of them using Sections, so for documents from June to make a section Like June 2022, for documents from August August 2022. Basically, I want to display all the documents, but each document to be displayed in the correct Month by using a section.
I'll share bellow what I tried.
The screen :
struct DocumentsListScreen: View {
#ObservedObject var viewModel : DocumentsViewModel
init(viewModel: DocumentsViewModel)
{
self.viewModel = viewModel
viewModel.fetchDocuments()
}
var body: some View {
if viewModel.presentingLoader {
LoaderView()
}
else {
List {
ForEach(viewModel.getUniqueDates(), id: \.self) { date in
Section(header: Text(viewModel.prettyDate(date))
.foregroundColor(.red)) {
ForEach(viewModel.arrayByDate(), id: \.idid) { doc in
VStack {
Text(doc.category)
Text(doc.title)
Text(doc.isPersonDoc)
Text(doc.isPersonDoc)
Text(doc.date)
}
}
}
}
}
}
}
}
The View Model :
class DocumentsViewModel : ObservableObject {
#Injected private var documentsUseCase: DocumentsUseCaseProtocol
#Published var documentsAssetsData: [DocumentsAssetsData] = []
#Published public var presentingLoader = true
var newArray: [String] = []
func fetchDocuments() {
documentsUseCase.performDocumentsRequest { [weak self] result in
switch result {
case .success(let response):
self?.documentsAssetsData = response
self?.presentingLoader = false
case .failure(_):
break
}
}
}
func prettyDate(_ date: String) -> String {
let dateFormatterGet = DateFormatter()
dateFormatterGet.dateFormat = "yyy.MM.dd"
let dateFormatterPrint = DateFormatter()
dateFormatterPrint.dateFormat = "MMMM yyyy"
let formattedDate: Date? = dateFormatterGet.date(from: date)
guard let date = formattedDate else {
return ""
}
return dateFormatterPrint.string(from: date)
}
func getUniqueDates() -> [String]{
for item in documentsAssetsData {
newArray.append(prettyDate(item.date))
}
let uniqueDates = newArray.compactMap { $0 }
let datesArray = Array(Set(uniqueDates))
let formatter = DateFormatter()
let output = datesArray
.map { (string: $0, date: formatter.date(from: $0)) }
.sorted {
guard let date1 = $0.date else { return true }
guard let date2 = $1.date else { return false }
return date1 > date2
}.map { $0.string }
return output
}
func arrayByDate() -> [DocumentsAssetsData]{
let items = documentsAssetsData.filter {prettyDate($0.date) == getUniqueDates().first}
return items
}
}
The json file that correspond to the Model I'm using, maybe it will help.
[
{
"idid": "1",
"title": "Document nr.4",
"category" : "Tax documents",
"date": "2022-08-08",
"isPersonDoc": false,
"productId": "4",
"personName": "Marie-Ange Schramm",
"productName": "Product Name 4",
"bpNr": 121324600
},
{
"idid": "2",
"title": "Document nr.5",
"category" : "Tax documents",
"date": "2022-08-09",
"isPersonDoc": false,
"productId": "5",
"personName": "Alessia Ackermann",
"productName": "Product Name 5",
"bpNr": 121324700
}
]
Also, another problem is that the title of the section is missing ( I don't know why ), but I tried to debug it and there are datas there .
Debugging the output for getUniqueDates()
Printing description of output:
▿ 4 elements
- 0 : "Juli 2022"
- 1 : "Juni 2022"
- 2 : "August 2022"
- 3 : "Mai 2022"
I'll share here a picture with the actual state of the List. Check image
Thanks a lot !

How to prune a tree of selective nodes without recursion

I can't solve the following problem without recursion. I get that the solution has to do with making a list of nodes to process but that's where I get stuck.
The problem is to remove all nodes from a tree with a negative value. I wrote an example in Swift below and included the recursive solution I came up with. What is the solution to the problem without using recursion?
struct Tree: Codable {
enum CodingKeys: String, CodingKey {
case children
case value
}
let children: [Tree]
let value: Int
}
let tree = Tree(children: [
Tree(children: [
Tree(children: [], value: 3),
Tree(children: [], value: -1)
], value: 5),
Tree(children: [
Tree(children: [], value: 3)
], value: -2)
], value: 12)
func prune(tree: Tree) -> Tree? {
if tree.value < 0 {
return nil
}
return Tree(children: tree.children.compactMap { child in
prune(tree: child)
}, value: tree.value)
}
let prunedTree = prune(tree: tree)
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let json = try! encoder.encode(prunedTree)
print(String(data: json, encoding: .utf8)!)
// {
// "value" : 12,
// "children" : [
// {
// "value" : 5,
// "children" : [
// {
// "value" : 3,
// "children" : [
//
// ]
// }
// ]
// }
// ]
// }

How do I map and filter JSON nested data dictionary below a certain number?

I've got a static JSON file, and am decoding it back successfully. However, I'm really struggling with storing it properly as it is nested a few layers deep. Currently the console prints out
["Hamilton", "Chermside", "Coorparoo"]
However, I need it to filter and return the values in each suburb that fall under 500000. So something like this would be great.
"Hamilton"
"oneBRU": 341000,
"twoBRU": 480000
"Chermside"
"oneBRU": 320000,
"twoBRU": 255000,
"threeBRU": 435000,
"twoBRH": 400000
The static JSON file is at the bottom. Thanks very much
var suburbsJson: [Suburb] = []
struct ResponseData: Codable {
var suburbs: [Suburb]
}
struct Suburb : Codable {
var _id: Int
var name: String
var postcode: Int
var prices: SuburbPrices
}
struct SuburbPrices: Codable {
let oneBRU: Int
let twoBRU: Int
let threeBRU: Int
let twoBRH: Int
let threeBRH: Int
let fourBRH: Int
}
func loadJson(filename fileName: String) -> [Suburb]? {
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
do {
let data = try Data(contentsOf: url)
let decoder = JSONDecoder()
let jsonData = try decoder.decode(ResponseData.self, from: data)
self.suburbsJson = jsonData.suburbs
let suburb = suburbsJson.map { $0.name }
print(suburb)
// print only suburbs below 500000
return jsonData.suburbs
} catch {
print("error:\(error)")
}
}
return nil
}
JSON FILE
{
"suburbs": [
{
"_id": 1,
"name": "Hamilton",
"postcode": 4007,
"prices":
{
"oneBRU": 341000,
"twoBRU": 480000,
"threeBRU": 880000,
"twoBRH": 555000,
"threeBRH": 945000,
"fourBRH": 1200000
}
},
{
"_id": 2,
"name": "Chermside",
"postcode": 4032,
"prices":
{
"oneBRU": 320000,
"twoBRU": 255000,
"threeBRU": 435000,
"twoBRH": 400000,
"threeBRH": 585000,
"fourBRH": 860000
}
},
{
"_id": 3,
"name": "Coorparoo",
"postcode": 4151,
"prices":
{
"oneBRU": 323000,
"twoBRU": 359750,
"threeBRU": 535000,
"twoBRH": 500000,
"threeBRH": 750000,
"fourBRH": 970000
}
}
]
}
If you just need to print the values, you could do something like this:
func loadJson(filename fileName: String) -> [Suburb]? {
if let url = Bundle.main.url(forResource: fileName, withExtension: "json") {
do {
let data = try Data(contentsOf: url)
let decoder = JSONDecoder()
let jsonData = try decoder.decode(ResponseData.self, from: data)
self.suburbsJson = jsonData.suburbs
// print only suburbs below 500000
jsonData.suburbs.forEach { suburb in
print(suburb.name)
if suburb.prices.oneBRU < 500000 {
print("One BRU: \(suburb.prices.oneBRU)")
}
if suburb.prices.twoBRU < 500000 {
print("Two BRU: \(suburb.prices.twoBRU)")
}
if suburb.prices.threeBRU < 500000 {
print("Three BRU: \(suburb.prices.threeBRU)")
}
if suburb.prices.twoBRH < 500000 {
print("Two BRH: \(suburb.prices.twoBRH)")
}
if suburb.prices.threeBRH < 500000 {
print("Three BRH: \(suburb.prices.threeBRH)")
}
if suburb.prices.fourBRH < 500000 {
print("Four BRH: \(suburb.prices.fourBRH)")
}
}
return jsonData.suburbs
} catch {
print("error:\(error)")
}
}
return nil
}

Can't print google's vision API results to app screen

I'm using Google's Vision API to identify certain features in an image. I have the Logo Detection working as the logo comes up in my terminal, but I can't get it to appear on my app screen. It continually prints "No logos found" - here's my code :
//Get logo annotations
let logoAnnotations: JSON = logoResponses["logoAnnotations"]
let numLogos: Int = logoAnnotations.count
var logos: Array<String> = []
if numLogos > 0 {
var allResultsText:String = "Logos: "
for index in 0..<numLogos {
let logo = logoAnnotations[index]["logo"].stringValue
logos.append(logo)
}
for logo in logos {
if logos[logos.count - 1] != logo {
allResultsText += "\(logo), "
} else {
allResultsText += "\(logo)."
}
}
self.allResults.text = allResultsText
} else {
self.allResults.text = "No logos found"
}
}
This is the JSON response I'm getting:
[
{
"boundingPoly": {
"vertices": [
{
"x": 210,
"y": 139
},
{
"x": 229,
"y": 139
},
{
"x": 229,
"y": 179
},
{
"x": 210,
"y": 179
}
]
},
"mid": "/m/04lg33",
"score": 0.18314756,
"description": "Ralph Lauren Corporation"
}
]
How am I to access the value returned for the logo description, this case Ralph Lauren Corporation?
I corrected the issue in my code. Here is the functioning code for anyone that needs it:
let logoAnnotations: JSON = responses["logoAnnotations"]
let numLogos: Int = logoAnnotations.count
var logos: Array<String> = []
if numLogos > 0 {
var logoResultsText:String = " ,"
for index in 0..<numLogos {
let logo = logoAnnotations[index]["description"].stringValue
logos.append(logo)
}
for logo in logos {
if logos[logos.count - 1] != logo {
logoResultsText += ", \(logo), "
} else {
logoResultsText += "\(logo)."
}
}
self.logoResults.text = logoResultsText
} else {
self.logoResults.text = ""
}
I was calling the incorrect index from the logoAnnotations array.

String is not convertible from Dictionary<String,AnyObject> Error in Swift

I've been battling this for too long. I have no idea
var a : [[String:AnyObject]] = [
[
"this":12
]
]
var b = "this"
func findAllKV(array: [[String:AnyObject]], key: String, value: AnyObject) -> [[String:AnyObject]] {
var all : [[String:AnyObject]] = []
for dict in array {
if dict[key] == value {
all.append(dict)
}
}
return all
}
findAllKV(a, b, 12)
I'm just trying to make a function that searches though an array of dictionaries and finds all with the matching key value
Try this one - println() helps reveal the issue:
var a : [[String:AnyObject]] = [
[
"this":12,
"test":13
],
[
"me":15,
"you":16
]
]
var b = "you"
func findAllKV(array: [[String:AnyObject]], key: String, value: AnyObject) -> [[String:AnyObject]] {
var all : [[String:AnyObject]] = []
for dict in array {
println(dict)
println(dict[key])
if let value: AnyObject = dict[key] {
println(value)
all += dict
}
}
return all
}
findAllKV(a, b, 12)
dict[key] returns an optional value. Try unwrapping it before checking:
var a : [[String:AnyObject]] = [
[
"this":12
]
]
var b = "this"
func findAllKV(array: [[String:AnyObject]], key: String, value: AnyObject) -> [[String:AnyObject]] {
var all : [[String:AnyObject]] = []
for dict in array {
if let val: AnyObject = dict[key] {
if val === value {
all.append(dict)
}
}
}
return all
}
var x = findAllKV(a, b, 12)
println(x) //[[this : 12 ]]