Merging a complex data structure of NSArray and NSDictionary - ios

I have the following data structure Snapshot which is a combination of nested arrays and dictionaries:
{"Snapshot": {
"ask": [
{
"price": 101.42,
"size": 7
},
{
"price": 101.85,
"size": 5
}
],
"bid": [
{
"price": 89.72,
"size": 79
},
{
"price": 89.71,
"size": 158
}
]
}}
The existing structure from above should be updated by the price and size entries in the following dictionary / array structure:
{"Refresh": {
"ask": [],
"bid": [
{
"price": 89.71,
"size": 666
}
],
}}
In this example, the value size for the bid item which has the price: 89.71 should be updated from 158 to 666. If the price does not exist yet, a new item with the price and size from the Refresh data structure should be added. If size = 0, the price and size item should be removed.
I have tried to do this with the methods addEntriesFromDictionary and addObjectsFromArray but did find a solution to my problem.
What would be the fastest way to do this?
How would you recommend to merge these two data structures?
Thank you!

Assuming the dictionaries are named snapshot and refresh...
snapshot[#"Snapshot][#"bid"] = [snapshot[#"Snapshot][#"bid"] arrayByAddingObjectsFromArray:refresh[#"Refresh"][#"bid]];
More complicated union of the arrays will just require more code. And if you want price to be a unique key, why not make it a key?

Related

How to read multidimensional JSON data in google sheet appscript?

How can I read this type of json data like I want profession of ID:12311 in google spreadsheet?
{
"user": [
{
"id": 12311,
"name": "Deffy doof",
"profession": "Photographer"
},
{
"id": 18341,
"name": "John Smith",
"profession": "Developer"
}
]
}
Solution:
Since this is an array of objects you can reference elements using array notation, e.g., to pull "Photographer":
data.user[0].profession
Sample:
If you only know the unique ID and not the index, you can filter the array first, then get the element.
var array = data.user.filter(function b(e) { return e.id == 12311 });
console.log(array[0].profession);
References:
filter()

Configuring collectionView:cellForRowAt based on an array of strings

I've got this JSON data (not verbatim) that I get from the backend. It contains the actual data and an array of strings describing the sequence of cells to be shown:
{
"data": [
{
"name": "text",
"data": {
"text": "some text"
}
},
{
"name": "pic",
"data": {
"url": "https://somepic.jpg",
"text": "picture"
}
},
{
"name": "switcher",
"data": {
"id": 1,
"options": [
{
"id": 0,
"text": "option 1"
},
{
"id": 1,
"text": "option 2"
},
{
"id": 2,
"text": "option 3"
}
]
}
}
],
"view": [
"text",
"pic",
"switcher",
"text"
]
}
The problem is that I can't get my head around how to configure cellForRowAt: and get the right order of cells in one section. (i.e. text, pic, selector, text).
I tried a couple of things:
Looping through "view" array and switching on each individual view string to dequeue a specific cell but that doesn't seem to work since returning a cell from a switch case gives a "unexpected non-void return value in void function" error.
I was also thinking about turning a "view" array into a dictionary and then, based on keys in it, dequeue a specific cell but then again, a dictionary should have unique keys meaning that I will not have 2 "text" entries, one of them will be lost.
So, the questions is: how can I dequeue specific cells based on the array of strings? It's also important to understand that it should be done in one section. I'm feeling that it's somehow not that difficult to implement but I'm kinda lost right now. Thanks!
you need to transform your view list and data array into an array of cell contents that you can use inside the TableViewDelegate and TableViewSource method :
var cellsContents : [Int] = []
for aView in view {
var found = false
var index = 0
for aData in data {
if !found {
if let name = aData["name"] as? String {
if aView == name {
found = true
cellsContents.append(index)
continue
}
}
index = index + 1
}
}
}
Then :
number of rows : cellsContents.count
type and contents for a row : data[cellsContents[indexPath.row]]["name"] and data[cellsContents[indexPath.row]]["data"]

Issue on JSON nested Array objects into TableVIew

I've tried many ways but i'm unable get the data from Something Array and show it in UITableView based on indexPath.
something is like below response
{
"results": [
{
"Something": [
[
{
"airV": "LX",
"class": "Y"
}
]
],
},
{
"Something": [
[
{
"airV": "FZ",
"class": "Y"
}
],
[
{
"airV": "FZ",
"class": "Y"
}
]
],
},
],
}
Note : something array [] ->>> contains many arrays in it.Looping the something array i want to get "airV": "LX","class": "Y"
airv,class into TableView
You can store the NSArray of (something) and iterate over that array based on NSIndexPath.
NSArray * arrayofSomething /* Your Array */
Inside your cellForRowAtIndexPath you can get the objects from arrayofSomething based on index.
Obj *obj = [arrayofSomething objectAtIndex:indexPath.row];

Different Cells in same UITableView

I have got a json result, that looks like this:
[{
"EventDate": "2015-02-19",
"PubEvents": [{
"Title": "Ladies Night",
"Description": "Every thursday is Ladies Night at the Irish House.\nLadies: 2 cocktails for the price of 1 - 1 pint of Crowmoor Cider - 30 kr",
"EventType": "LadiesNight",
"Start": "2015-02-19",
"End": "2015-02-20",
"StartTime": "19:00",
"EndTime": "02:00",
"Image": "ladies.jpg"
}, {
"Title": "Pat Kelly",
"Description": "Pat Kelly from Ireland has extensive experience in entertaining all nationalities, as he has travelled around the world from New York to Amsterdam. He has a very wide repertoire maintaining a traditional approach, and is well received and appreciated for his ability to get his audience excited every night he hits the stage. A “sure thing” evening you will get with the talented Pat.",
"EventType": "Music",
"Start": "2015-02-19",
"End": "2015-02-20",
"StartTime": "21:30",
"EndTime": "01:00",
"Image": "http://domain.dk/Images/Musicians/kelly"
}],
"Matches": [{
"EventType": "Sports",
"Start": "2015-02-19",
"End": "2015-02-19",
"StartTime": "18:00",
"EndTime": "19:00",
"HomeTeam": {
"Id": 0,
"TeamName": "Hold",
"HomeImageUrl": "defaultHome.png",
"AwayImageUrl": "defaultAway.png",
"Badge": "defaultBadge.png"
},
"AwayTeam": {
"Id": 0,
"TeamName": "AndetHold",
"HomeImageUrl": "defaultHome.png",
"AwayImageUrl": "defaultAway.png",
"Badge": "couldn't get an away team"
}
}]
}, {
"EventDate": "2015-02-20",
"PubEvents": [{
"Title": "Pat Kelly",
"Description": "Pat Kelly from Ireland has extensive experience in entertaining all nationalities, as he has travelled around the world from New York to Amsterdam. He has a very wide repertoire maintaining a traditional approach, and is well received and appreciated for his ability to get his audience excited every night he hits the stage. A “sure thing” evening you will get with the talented Pat.",
"EventType": "Music",
"Start": "2015-02-20",
"End": "2015-02-21",
"StartTime": "22:30",
"EndTime": "02:00",
"Image": "http://domain.dk/Images/Musicians/kelly"
}],
"Matches": []
},
An Array of Events in the format:
var eventDate : String?
var pubEvents : Array<PubEvent>?
var matches : Array<Match>?
numberOfSectionsInTableView is eventarray.count, as every date is distinct
numberOfRowsInSection:
let event = self.eventarray[section]
let matchesCount = event.matches?.count ?? 0
let pubEventsCount = event.pubEvents?.count ?? 0
return matchesCount + pubEventsCount
Since every section has x number of matches and x number of pubEvents i need a combined count of the amount of each.
Here is my problem:
I would need to insert the pubevents (if any) and the matches (if any) in the tableview, but I can't figure it out with Swift.
Edit
Philip Mills helped: A very quick implementation:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
let event = self.eventarray[indexPath.section] as SortedEvent
let matchesCount = event.matches?.count ?? 0
let pubEventsCount = event.pubEvents?.count ?? 0
if indexPath.row < matchesCount{
cell.textLabel?.text = "\(event.matches![indexPath.row].homeTeam!.teamName!) v \(event.matches![indexPath.row].awayTeam!.teamName!)"
cell.detailTextLabel?.text = "\(event.matches![indexPath.row].startTime!) - \(event.matches![indexPath.row].endTime!)"
}
else{
cell.textLabel?.text = event.pubEvents![indexPath.row - matchesCount].title!
cell.detailTextLabel?.text = "\(event.pubEvents![indexPath.row - matchesCount].startTime!) - \(event.pubEvents![indexPath.row - matchesCount].endTime!)"
}
return cell
}
When you're given an index path to provide a cell, see if the row is less than the count of matches. If it is, use that match. If it's not less, subtract the count of matches from the row and use that as the index of the pub event you want.

iOS: Switching from JSON to CoreData for keeping local persistent data; is this practical? Dictionary within array within dictionary within array

I started last month with Swift and iOS. I'm working on an iPhone fitness app, specifically for weightlifting. Until now I've just been using a JSON file in the app's documents folder to store all the user's workouts, and using let workoutData = NSJSONSerialization.JSONObjectWithData( . . . ) as NSArray to load the data from the file (for display in a UITableView-like format) and then adding new workout entries with:
let newEntry: NSData = NSJSONSerialization.dataWithJSONObject(newData, options: .PrettyPrinted, error: nil)
newEntry.writeToFile(documentsPath, atomically: true)
This worked fine at first, but now I need to be able to edit workouts, add new ones at arbitrary dates, or delete specific workouts. This requires a fair amount of looping through arrays within dictionaries within arrays, and sorting the workouts properly has become difficult.
I feel like CoreData may be the best option going forward, considering the nature of my data. That said, here's an example of the structure of my JSON database:
[
{
"day": "Thursday",
"date": "June 5 2014",
"lbs": true,
"lifts": [
{
"name": "SQUAT",
"sets": 1,
"reps": 5,
"weight": 205,
"warmup": true
},
{
"name": "SQUAT",
"sets": 3,
"reps": 5,
"weight": 245,
},
{
"name": "BENCH PRESS",
"sets": 1,
"reps": 5,
"weight": 135,
"warmup": true
},
{
"name": "BENCH PRESS",
"sets": 3,
"reps": 5,
"weight": 185
},
{
"name": "YATES ROW",
"sets": 3,
"reps": 5,
"weight": 135,
}
]
},
{
"day": "Wednesday",
"date": "June 3 2014",
"lbs": true,
"lifts": [
{
"name": "DEADLIFT",
"sets": 1,
"reps": 3,
"weight": 255,
"warmup": true
},
{
"name": "DEADLIFT",
"sets": 1,
"reps": 5,
"weight": 305,
},
{
"name": "OVERHEAD PRESS",
"sets": 1,
"reps": 5,
"weight": 95,
"warmup": true
},
{
"name": "OVERHEAD PRESS",
"sets": 3,
"reps": 5,
"weight": 125
},
{
"name": "CHIN-UPS",
"sets": 3,
"reps": 5,
"weight": 180,
}
]
},
{
"day": "Monday",
"date": "June 1 2014",
"lbs": true,
"lifts": [
]
}
]
So the structure is:
Top level array, containing each workout day dictionary
Workout day dictionary, with a day string, date string, and an array of lifts
Array of lifts, each lift itself a dictionary
Lift dictionary, containing the lift name, sets, reps, weight, and a bool indicating whether this was a warmup set.
CoreData entities seem to only allow rather simple attributes. I suppose I could use a "Transformable" attribute, or use lots of To-Many relationships, but I'd rather not go to the trouble of learning those if it's not necessary.
So, should I suck it up and figure out how to make this same structure happen in CoreData? Alternatively, is this data structure too complex? Should I get rid of arrays/dictionaries altogether and just have a flat "workout" entity, and then after loading data from CoreData, collect all the workouts of the same date/type into groups manually in a ViewController?
Or, given the nature of my data, is there something better suited to use rather than CoreData or JSON? SQLite, perhaps?
If I were you I'd use CoreData or CloudKit (for online storage). The reason why is if I'm a user and I've got workouts spanning a year and a ton of data within each workout. That's going to take forever to load into memory. So you're going to have to figure out a way to segment your data anyways or else your users could be waiting a while for the file to be read into memory or possibly, the file could get bigger than is allotted and it wouldn't be possible to read in.
I don't know why you're saying it would be difficult to store these into database. It looks like to me you already have a structure that could be translated to a DBMs fairly easily. You're tables I would think should look something like this:
Workout : Table #1
wid (primary key)
date (timestamp)
lifts (array of: foreign keys)
Lifts : Table #2
lid (primary key)
name (string)
sets (number)
reps (number)
weight (number)
warmup (bool)
Don't be scared of Databases, they're really not that bad and it'll be 1000% more efficient than storing them in files.

Resources