Swift automatically creating temporary dictionaries - ios

I'm working with a datasource for a UITableView where I need an array with dictionaries.
I tried making an array, and filling it with dictionaries in a for loop like this.
temporaryDataDict = [:]
temporaryDataDict = ["name":stockName, "ticker":ticker, "lastPrice":lastPrice, "purchasePrice":purchasePrice, "weight":weight, "daysHeld":daysHeld]
temporaryDataArray.append(temporaryDataDict)
But of course, when I start filling my tableView with the dataSource. I end up for 23 of the exact same dictionaries (the last one in the for loop).
This is of course, because it's changing the dictionary every time.
I havn't been able to find a way to keep the data in the dictionaries, or programatically make a new dictionary every time (since they need a new name otherwise it'll overwrite the data).
So how can I programatically make dictionaries everytime a for loop runs, then get the keys & values of these dictionaries?
or am I going about this completely wrong?
If it helps, here's the kind of data I'm working with.
I have a stock (or item) with 6 properties. So I think it makes the most sense to have an array where every item in the array is the "stock" as a dictionary that contains the 6 properties.
So is it possible to make swift automatically create these dictionaries for me? Since I don't know the amount of dictionaries needed.
PS.
I know this is what CoreData is for. I'm using these arrays and Dictionaries to later fill in my CoreData.
If the above isn't possible I am aware that I can probably create a new CoreData entity to accomplish what I want, but it doesn't seem like the best way to go about it.
Any help would be greatly appreciated! Thanks

I don't believe that a dictionary is the best sort of data structure to use in this case. Since typically a dictionary is composed of a unique key and a value.
I have edited this answer. Originally I suggested creating a class containing a property for each record field. Then I figured that this could be done using a tuple via a typealias for each record. Using a typealias gets around an issue related to creating arrays of tuples.
ETA: However please read the comments because Zaph who knows more about this than me reckons that using a Class is a stronger solution.
This is my tuple based solution. Most of what follows is just about quickly creating some dummy data:
typealias StockRecord = (stockName:String, ticker: String, lastPrice: Double, purchasePrice: Double, weight: Double, daysHeld: Int)
var temporaryDataArray = [StockRecord]()
// use a loop to create dummy records and add each to the array
// rough and ready - just to test the solution
var loopCounter: Int
for loopCounter = 0; loopCounter <= 23; loopCounter++ {
//some dummy field values for each record
var stockName = "stockName" + ("\(loopCounter)")
var ticker = "ticker" + ("\(loopCounter)")
var lastPrice = Double(loopCounter)
var purchasePrice = Double(loopCounter)
var weight = Double(loopCounter)
var daysHeld = loopCounter
var newRecord = (stockName, ticker, lastPrice, purchasePrice, weight, daysHeld)
temporaryDataArray.append(newRecord)
}
ETA: Iterate over the array - eg:
for recordEntry in temporaryDataArray {
var a = recordEntry.stockName
var b = recordEntry.ticker
// etc
}
Or with enumeration - eg:
for (count,recordEntry) in enumerate(temporaryDataArray) {
println("\(count) \(recordEntry)")
}
Output:
0 (stockName0, ticker0, 0.0, 0.0, 0.0, 0)
1 (stockName1, ticker1, 1.0, 1.0, 1.0, 1)
2 (stockName2, ticker2, 2.0, 2.0, 2.0, 2)
3 (stockName3, ticker3, 3.0, 3.0, 3.0, 3)
etc

Related

Using CoreData to save array containing dictionaries

I'm trying to use CoreData framework inside an iOS app for the first time and I have some troubles with it.
I have a kind of complex type of array, containing tuples that contains dictionaries:
let DataSet: [( Float, Float, [String : String])] = ...
I created an NSManagedObjectContext and an NSManagedObject, I added the DataSet array to the NSManagedObject, but when I try to save the 1st NSManagedObjectContext, the app is crashing.
That's not happening using normal arrays but only with more complex ones like the one above.
Is there a way to deal with that problem? Do I need to adjust my xcdatamodel?
I would appreciate any help a lot.
First you need to declare 2 separate entities. One for Floats and another for Dictionary.
Then create "One to Many" relation ship between Float entity and Dictionary. It will look like this,
Then you need to convert your tuple into these 2 entities, Like this,
dataSet.forEach{ (member) in
let tuple = Test.(context: mainContext)
tuple.first = member.0
tuple.second = member.1
let dictionary = member.2
dictionary.forEach{ (key, value) in
let dick = Dick.(context: mainContext)
dick.key = key
dick.value = value
tuple.addToContains(dick)
}
}
Finally you need to save the values.
if mainContext.hasChanges {
do {
try mainContext.save()
} catch {
print(\(error))
}
}

Appending items to an array in dictionary not working

I have this static dictionary created as so:
static var pictures = Dictionary<Int, Array<UIImage>>()
I want to populate it with images. At the moment when I am creating it I don't know how many key/value pairs I need to create. I have to fetch from the internet the data, but after that I am doing this to populate, but still my dictionary is empty:
for i in 0...Fetching.numberOfAliveListings - 1 {
for _ in 0...AdsCollectionView.listings[i].photos.count - 1 {
AdsCollectionView.pictures[i]?.append(UIImage(named: "noimage")!)
}
}
pictures is initially empty. So any attempt to access a value for a given key will result in a nil value. Since the value (the array) is nil, the optional chaining skips the call to append.
One solution is to provide a default array when looking up the value for a given Int.
AdsCollectionView.pictures[i, default: []].append(UIImage(named: "noimage")!)
You may also wish to consider alternate syntax when declaring pictures:
static var pictures = [Int: [UIImage]]()

Swift 3 build array (Don't know how to describe)

First of all, sorry for the unclear title, but I don't know how to describe my problem or how to search for it. (Still a beginner)
So I have an array where I need to put values in.
let heliosDataArray:String = "[{\"timestamp\":\"\(timestamp)\",\"uv\":\"\(uvIndex!)\",\"light\":\"\(lightvalue!)\"}]"
So in this "template" I need to add 3 values: timestamp, uvIndex and lightValue. So far so good. Now I have a lot of values and for an API call I need to to chain this array multiple times in to 1 array, kind of like a master array. What is the most practical way of doing this? The amount of data is variable, and comes from CoreData. Probably going to put the values first in arrays. What should I be searching for? I was thinking a loop but like more advanced?
Thanks in advance
You can approach with object-oriented logic:
struct Data {
var timestamp: Double?
var lightValue: Double?
var uvIndex: Int?
}
let data1 = Data(timestamp: 13.4, lightValue: 3.4, uvIndex: 4)
let data2 = Data(timestamp: 12.4, lightValue: 2.4, uvIndex: 3)
let data3 = Data(timestamp: 11.4, lightValue: 1.4, uvIndex: 2)
var dataArray = Array<Data>() // or-> var data = [Data]()
dataArray.append(data1)
dataArray.append(data2)
dataArray.append(data3)
You can do this in many ways. One of them is shown below
let say you have three values from coredata timestamp, uvIndex and lightvalue
Seems what you are asking is a array of dictionaries, first you need is a dictionary of the values you got from CoreData, let call them dayItem
var dayItem = ["timestamp": timestamp,
"uv": uvIndex,
"light": lightValue]
Now create an array of values
var dayArray: [[String: Any]] = []
dayArray.append(dayItem)
Every time you want to append new items just use the append method of array

"Preloading" A Dictionary With Keys in Swift

This is a fairly simple issue, but one I would like to solve, as it MAY help with performance.
I want to find out if Swift has a way to create a Dictionary, specifying ONLY keys, and maybe no values, or a single value that is set in each entry.
In other words, I want to create a Dictionary object, and "preload" its keys. Since this is Swift, the values could be 0 or nil (or whatever is a default empty).
The reason for this, is so that I can avoid two loops, where I go through once, filling a Dictionary with keys and empty values, and a second one, where I then set those values (There's a practical reason for wanting this, which is a bit out of the scope of this question).
Here's sort of what I'm thinking:
func gimme_a_new_dictionary(_ inKeyArray:[Int]) -> [Int:Int] {
var ret:[Int:Int] = [:]
for key in inKeyArray {
ret[key] = 0
}
return ret
}
let test1 = gimme_a_new_dictionary([4,6,1,3,0,1000])
But I'm wondering if there's a quicker way to do the same thing (as in "language construct" way -I could probably figure out a faster way to do this in a function).
UPDATE: The first solution ALMOST works. It works fine in Mac/iOS. However, the Linux version of Swift 3 doesn't seem to have the uniqueKeysWithValues initializer, which is annoying.
func gimme_a_new_dictionary(_ inKeyArray:[Int]) -> [Int:Int] {
return Dictionary<Int,Int>(uniqueKeysWithValues: inKeyArray.map {($0, 0)})
}
let test1 = gimme_a_new_dictionary([4,6,1,3,0,1000])
For Swift 4, you can use the dictionary constructor that takes a sequence and use map to create the sequence of tuples from your array of keys:
let dict = Dictionary(uniqueKeysWithValues: [4,6,1,3,0,1000].map {($0, 0)})
I presume you could optimize your code in terms of allocation by specifying the minimum capacity during the initialization. However, one liner may be the above answer, it's essentially allocation and looping to add 0 in each position.
func gimme_a_new_dictionary(_ inKeyArray:[Int], minCapacity: Int) -> [Int:Int] {
var ret = Dictionray<Int, Int>(minimumCapacity: minCapacity)
for key in inKeyArray {
ret[key] = 0
}
return ret
}
let test1 = gimme_a_new_dictionary([4,6,1,3,0,1000])
Take a look at this official documentation:
/// Use this initializer to avoid intermediate reallocations when you know
/// how many key-value pairs you are adding to a dictionary. The actual
/// capacity of the created dictionary is the smallest power of 2 that
/// is greater than or equal to `minimumCapacity`.
///
/// - Parameter minimumCapacity: The minimum number of key-value pairs to
/// allocate buffer for in the new dictionary.
public init(minimumCapacity: Int)

How to Make a Struct Version of the NSCountedSet Class?

I am developing an app in which I need to take two arrays, both holding the same custom data type, MenuItem.
I need to compare them and find the common elements of both arrays.
I compare the two arrays by converting them both to sets and then using the compare function of the set struct.
However, I then need to convert the array of common elements to a Counted Set so that I can find how many of each element exist in the group of common elements.
The problem I am having is with converting the the array of common elements to a Counted Set. In Swift, there is an NSCountedSet class but no CountedSet struct like there are for most built-in swift Data Types:
let groups = Array(self.menu.keys)
//menu and cart are dictionaries the structure [MenuGroup: [MenuItem]]
let cartGroups = Array(self.cart.keys)
let group = groups[indexPath.section]
if cartGroups.contains(group) {
let items = menu[group] as [MenuItem]!
let cartItems = cart[group]
let itemsSet = Set<MenuItem>(items!)
let cartItemsSet = Set<MenuItem>(cartItems!)
let similarSet = itemsSet.intersection(cartItemsSet)
let similarArray = NSMutableArray(Array(similarSet))
let similarCounterSet = NSCountedSet(array: similarArray)
}
I want to create a struct based off the NSCountedSet class so that I can convert the array of common elements to a counted set.
The if statement is for something else, it does not pertain to this question.
Any thoughts on how to do this? If anybody has a different approach to this problem feel free to mention that too.
Thanks,
Simon
Thanks to Martin R I Found An Example of How to do This:
There are various CountedSet implementation available, e.g. https://github.com/0x7fffffff/CountedSet.

Resources